2016-05-05 150 views
5

我有一個包含大量文檔(32 809 900)的集合。所有文件都有一個名爲soft_deleted的字段。我也創建了soft_deleted: 1字段。然後我測試了一些與該領域相關的不同查詢。以下是我的結果:MongoDB查詢索引字段很慢

Query        Number of results Time in milliseconds 
db.cgm_egvs 
    .find().count()     32809900   90 
db.cgm_egvs 
    .find({soft_deleted: true})  2820897   688 
    .count() 
db.cgm_egvs 
    .find({soft_deleted: false})  29989003   3983 
    .count() 
db.cgm_egvs 
    .find({soft_deleted: null})  0     42 
    .count() 
db.cgm_egvs 
    .find({soft_deleted: {$ne: true}}) 29989003   82397 
    .count() 

爲什麼這些查詢的查詢時間如此不同?我希望找到soft_deletedtruefalse的文檔需要花費相同的時間。 更重要的是,爲什麼通過!= true查詢比其他任何查詢慢得多?

+1

您可以在每個查詢廣告發布結果末尾添加**。explain(「executionStats」)**。這將允許獲得更多的執行細節。 – profesor79

+0

真實與虛假的差異可能由索引選擇性來解釋。例如,如果文檔中有10%的文檔具有soft_deleted:true,則該索引對於匹配soft_deleted:true非常有用。另一方面,當搜索soft_deleted:false時,索引是沒用的。 – joao

回答

3

的soft_deleted領域具有非常低的基數;它只有兩個截然不同的值是真實的和錯誤的,所以在這個領域有一個索引你沒有太大的好處。通常,索引在基數較高的字段上執行得更好。

在{soft_deleted:true}查詢的情況下,soft_deleted:true的行數與{soft_deleted:false}相比非常少,並且mongodb必須掃描更少數量的索引條目。所以{soft_deleted:true}查詢花費的時間更少。

類似地,查詢{soft_deleted:null}花費的時間較少,因爲索引只有2個不同的值,在這種情況下需要更低的掃描。

您的最終查詢使用$ ne運算符,而$ ne運算符不具有選擇性(選擇性是查詢使用索引縮小結果的能力)。 https://docs.mongodb.com/v3.0/faq/indexes/#using-ne-and-nin-in-a-query-is-slow-why。 所以花了很多時間來執行。

0

我不知道爲什麼其他查詢很慢(因爲我正在等待解釋轉儲), 但在$ ne的情況下,重點是我們在那裏添加了額外的步驟,這意味着此函數首先被等同並且然後不等於 - >參見下面解釋轉儲parsedQuery部分,然後找到一步

db.getCollection( 'A1')找到({等級:{$ NE: 「信息」}})。 .explain()

"queryPlanner" : { 
    "plannerVersion" : 1, 
    "namespace" : "logi.a1", 
    "indexFilterSet" : false, 
    "parsedQuery" : { 
     "$not" : { 
      "Level" : { 
       "$eq" : "Info" 
      } 
     } 
    }, 
。210

db.getCollection( 'A1')找到({級別: 「信息」})解釋()

"queryPlanner" : { 
    "plannerVersion" : 1, 
    "namespace" : "logi.a1", 
    "indexFilterSet" : false, 
    "parsedQuery" : { 
     "Level" : { 
      "$eq" : "Info" 
     } 
    },