2017-03-06 36 views
2

我需要複合指數爲我的收藏,但我不知道鑰匙訂購MongoDB的合成指數

我的項目:

{ 
    _id, 
    location: { 
     type:  "Point", 
     coordinates: [<lng>, <lat>] 
    }, 
    isActive: true, 
    till: ISODate("2016-12-29T22:00:00.000Z"), 
    createdAt : ISODate("2016-10-31T12:02:51.072Z"), 

    ... 

} 

我的主要查詢是:

db.collection.find({ 
    $and: [ 
     { 
      isActive: true 
     }, { 
      'till': { 
       $gte: new Date() 
      } 
     }, 
     { 
      'location': { $geoWithin: { $box: [ [ SWLng,SWLat], [ NELng, NELat] ] } } 
     } 

    ] 
}).sort({'createdAt': -1 }) 

在人類,我需要在我的地圖的可見部分沒有過期的所有活動項目,新添加 - 首先。

是正常創建這個索引:

db.collection.createIndex({ "isActive": 1, "till": -1, "location": "2dsphere", "createdAt": -1 }) 

什麼是性能最好的順序,對磁盤使用情況?或者,也許我必須創建幾個索引...

謝謝!

回答

2

領域的索引中的順序應該是:

  1. 領域上,您會爲精確值查詢。
  2. 要排序的字段。
  3. 您將在其上查詢一系列值的字段。

你的情況,那就是:

db.collection.createIndex({ "isActive": 1, "createdAt": -1, "till": -1, "location": "2dsphere" }) 

然而,在布爾字段指標往往不是非常有用,因爲平均MongoDB中仍然需要訪問你的文件的一半。所以,我勸你做到以下幾點:

  1. 重複採集用於測試目的
  2. 創建索引,你想測試(即{"isActive": 1, "createdAt": -1, "till": -1, "location": "2dsphere" }
  3. 在蒙戈外殼創建變量

    VAR EXP = db.testCollection.explain( 'executionStats')

  4. 執行以下查詢exp.find({'you query'})它將返回描述EXEC統計獲獎計劃

  5. 的ution分析像鑰匙: 「nReturned」, 「totalKeysExamined」, 「totalDocsExamined」
  6. 刪除索引,創建新的(即{"createdAt": -1, "till": -1, "location": "2dsphere"}),執行exp.find({'you query'})比較的結果與前一
+0

謝謝,阿列克 我要創建一些測試......但一些言論: isActive在〜95%是真實的,但由於某些原因的統計數據我做一些額外的查詢:'db.collection.find( {$和:[{isActive:true},{'till':{$ gte:new Date()}}]})'和'db.collection.find({$ and:[{isActive:true},{ 'till':{$ gte:new Date()}},{createdAt:{$ gte:today}}]})',無需排序和geo。 kyes訂單是否一樣? P.S.非常感謝來自敖德薩的基輔( - : – none

+0

))很好。對於'createdAt'字段用作過濾器的情況,索引順序是相同的。但是,如果查詢中沒有「createdAt」字段(既不在過濾器中,也不在排序中),建議的索引將不會被使用,可能最好爲'till'字段創建一個更多的索引。但請記住,額外的索引會降低寫入和刪除操作的性能 –

2

在蒙戈,很多事情取決於數據和訪問模式。在您的收藏上創建索引時,有幾件事情需要考慮 -

  1. 如何從應用程序訪問數據。 (您已經知道主要查詢,所以這部分幾乎完成)
  2. 數據大小和基數和數據範圍。
  3. 數據操作。(讀取和寫入的頻率將以何種模式發生)
  4. 特定查詢一次只能使用一個索引。
  5. 索引使用不是靜態的。 Mongo不斷改變啓發式使用的索引,並試圖以優化的方式進行。所以如果你在soem時間看到index1被使用,可能會發生mongo在輸入一些/足夠不同類型/基數的數據之後使用index2。

指數對於您的應用程序性能可能會更好,也更糟糕。在生產中使用它們之前,最好通過外殼/指南針進行測試。

var ex = db.<collection>.explain("executionStats") 

上面一行在蒙戈外殼進入時給你解釋的對象上的光標可進一步用來檢查性能問題。

ex.find(<Your query>).sort(<sort predicate>) 

注意要點在上面的輸出是

  • 「executionTimeMillis」
  • 「totalKeysExamined」
  • 「totalDocsExamined」
  • 「階段」
  • 「nReturned」

我們努力爭取前三項中的最小值(executionTimeMillis,totalKeysExamined和totalDocsExamined),並且「階段」是告訴發生了什麼的一件重要事情。如果Stage是「COLLSCAN」,那麼它表示它正在查找每個文檔以完成查詢,如果Stage是「SORT」,則表示它正在執行內存中的排序。兩者都不好。

來到您的查詢,有幾件事情需要考慮─

  1. 如果「直到」將不得不像一個月終止日期一固定值一個月期間輸入的所有項目,然後它不是一個好主意有索引。即使在此索引之後,數據庫也必須掃描許多文檔。此外,由於它是月結束日期,因此該指數在一年內只有12個條目。
  2. 如果「till」是「createdAt」之後的固定值,那麼兩者都有索引是不好的。
  3. 索引「isActive」不好,因爲它只能使用兩個值。

因此,請嘗試使用實際數據並執行以下指標,並確定哪些指數應該適合考慮時間,否。的文檔。審查等

1. {"location": "2dsphere" , "createdAt": -1} 
2. {"till":1, "location": "2dsphere" , "createdAt": -1} 

應用這兩個指標收集和執行ex.find()。sort()其中ex是可解釋的遊標。然後,您需要分析兩個輸出並進行比較才能做出最佳決定。

+0

非常感謝這樣一個真棒解釋! – none