Sails.js + MongoDB + UUID = 性能怪獸

記錄下去年的解決的大坑。

最近線上的MongoDB服務器(4Core ?8G RAM)硬件資源占用的有些奇怪,10分鐘內幾百個請求就可以輕松把這機器整的明明白白的。

在使用控制變量法排除排除IO瓶頸,帶寬瓶頸,服務器超賣等問題,順著鍋飛行軌跡來到了MongoDB身上。

通過MongoDB Database Profiler可以發(fā)現(xiàn)我們可愛的索引們似乎并沒有發(fā)揮作用。works這個數值竟然高達18w,這基本上是這張collection數據量。這就表示說我們的id索引似乎在混吃等死。

這基本等價于做全表掃描,所謂索引的意義在于我在海量的rows想要找到某一個row的時候不需要去掃描全部的rows,而是通過特定的數據結構采用空間換時間的辦法從而實現(xiàn)查詢加速。這種思路類似在數組中需要過濾數據的時我們只能不停的去遍歷item,判斷其是否符合條件。但如果把條件的結果作為key全部都壓到散列(Object)里面,這時只需要key就可以訪問到你想要的rows。當然了,目前數據庫引擎實現(xiàn)這種索引結構可沒有這么簡單,行業(yè)通行的做法是 B-Tree / B-Tree+。

但為什么索引不生效?其實索引是生效的,只不過掃描整表換成了掃描全部索引。這個時候繼續(xù)往filter里面看,好像filter里的value是正則耶,是 正 則 耶!!真是打擾了,索引的下來的id全部是string,但是在匹配的時條件是正則表達式。所以索引不能被直接命中,要不斷的遍歷啊。

但這種骨骼驚奇find寫法并沒有出現(xiàn)在的項目的代碼里面,這只能再去檢查Sails底層ORM(Waterline)的代碼。直接來到sails-mongo這個npm,找到在Query時候parseValue這個方法,嗯,看到了ObjectId。我從接盤開始就在使用UUID,我們先看代碼。

不是非常贊許sails團隊是這么實現(xiàn)關鍵sql拼接邏輯,雖說ObjectId是MongoDB官方推崇的實踐標準。但是強行把string變正則,在ORM中ParseValue這么關鍵的地方。而caseSensitive又是一個隱藏配置,就是那種你不去看源碼就發(fā)現(xiàn)不到的那種配置。好啦,原因已經找到了。要么換id type,要么sails-mongo fork出來改改代碼,要么把這個condition給跳出去吧。如果你想為sails提交PR,對不起,人家團隊比較穩(wěn)定,喜歡自己修。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容