二位陣列按照指定欄位拍下 乙個陣列查詢引發的坑

2021-10-14 18:58:26 字數 2084 閱讀 2439

背景

中午12點半,接到了線上mongodb 資料庫異常的告警通報:

「cpu不間斷飆公升到百分百,業務也相應出現了抖動現象。」

通過排查資料庫主節點的日誌,發現了這樣的乙個慢語句:

從語句中初步判斷,「key***amined」和doc***amined顯示掃瞄了100w 條記錄,其中也用到了下面的索引:

某些應用下帶指定標籤的裝置資訊,按id分段去獲取,每次只查詢10條。

關於索引的設計也已經確認過是最優的了,而且此前在開發環境中一直沒有出現過問題,不知道為什麼這次就出問題了。

詳細分析

接下來,看了下該集合的模型,大致是長下面的樣子:

說明

除了其他的屬性之外,tags欄位採用了巢狀文件陣列的結構;

每乙個元素都對應了乙個tag物件,包含 tagname/ta**alue/tagtype幾個字段。

然後是查詢的模式

id索引!

但同時,我們也從indexbounds的指示中找到了端倪:

由於中間索引節點出現了大範圍覆蓋,導致最終需要在記憶體中對大量的資料做 _id欄位的排序,這個就是導致慢操作的原因!

解決問題

既然索引的命中沒有問題,那麼導致大範圍掃瞄的只可能是查詢模式的問題。

再次拿出前面的查詢條件:

tags.tagname: 「pipeline」這乙個條件,那麼由於 tags是乙個巢狀文件的陣列,

對於上面的查詢,語義上是指那些包含某個元素 可命中tagname,且包含某個元素 可命中 ta**alue的文件,這裡面並不要求 同乙個元素同時命中tagname和ta**alue。

對於陣列元素的條件匹配,應該使用$elemmatch,其用法可參考這裡

為此,我們構建了下面的查詢:

最後,根據該方案調整了查詢模式,線上的問題得到恢復。

小結

看似很簡單的乙個查詢語句,沒想到會出現這麼大的坑,其實無論是作為開發人員還是dba,都應當謹慎對待你的sql。

重要的事情說三遍!!! sql查詢上線前務必 explain、務必分析到位,這難道沒有道理?

作者華為技術專家,多年網際網路研發/架設經驗,關注nosql 中介軟體高可用及彈性擴充套件,在分布式系統架構效能優化方面有豐富的實踐經驗,目前從事物聯網平台研發工作,致力於打造大容量高可用的物聯網服務。

C語言二位陣列

前言 今天在實現裝配線排程程式時候,用到了二維陣列,並將其作為函式的引數。在寫程式的時候,遇到一些問題,即二維陣列做函式的引數應該如何正確表示。我寫程式的錯誤如下程式所示 1 include 2 void print int a 3 3 67intmain 8 10print a 11return0...

二位陣列與指標

include include using namespace std void disparry int a 2 3 int main void c是乙個指標,指向的元素int 3 即arr的行元素 int c 3 arr int p p int arr p指向arr 0 0 也可以說是arr 0...

二位陣列傳參及二位陣列動態分配問題

二位陣列引數傳遞 1.void display1 int arr 4 const int rows cout endl cout endl 2.void display2 int parr 4 const int rows cout endl cout endl parr i 等價於 parr i ...