2017-08-23 70 views
1

Mongo Documentation後,爲什麼蒙戈查詢中FETCH空濾器進行IXSCAN

{ item : null }查詢相匹配,要麼包含 item字段的值是null或不包含item 領域的文件。

我找不到這個文件,但據我所知,這兩種情況下(值爲null或現場丟失)存儲在索引null

所以,如果我做db.orders.createIndex({item: 1}),然後db.orders.find({item: null}),我希望一個IXSCAN發現,要麼包含item字段的值是null或不包含item領域,只有這些文件的所有文件。

那麼,爲什麼不db.orders.find({item: null}).explain()FETCH登臺演出filter: {item: {$eq: null}}它執行IXSCAN後?可能需要過濾哪些文件?

{ 
    "queryPlanner" : { 
     "plannerVersion" : 1, 
     "namespace" : "temp.orders", 
     "indexFilterSet" : false, 
     "parsedQuery" : { 
      "item" : { 
       "$eq" : null 
      } 
     }, 
     "winningPlan" : { 
      "stage" : "FETCH", 
      "filter" : { 
       "item" : { 
        "$eq" : null 
       } 
      }, 
      "inputStage" : { 
       "stage" : "IXSCAN", 
       "keyPattern" : { 
        "item" : 1 
       }, 
       "indexName" : "item_1", 
       "isMultiKey" : false, 
       "isUnique" : false, 
       "isSparse" : false, 
       "isPartial" : false, 
       "indexVersion" : 1, 
       "direction" : "forward", 
       "indexBounds" : { 
        "item" : [ 
         "[null, null]" 
        ] 
       } 
      } 
     }, 
     "rejectedPlans" : [ ] 
    }, 
    "serverInfo" : { 
     "host" : "Andys-MacBook-Pro-2.local", 
     "port" : 27017, 
     "version" : "3.2.8", 
     "gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0" 
    }, 
    "ok" : 1 
} 

我想,也許undefined值將得到索引爲null,但簡單的實驗規則了這一點:

> db.orders.createIndex({item: 1}) 
{ 
    "createdCollectionAutomatically" : true, 
    "numIndexesBefore" : 1, 
    "numIndexesAfter" : 2, 
    "ok" : 1 
} 
> db.orders.insert({item: undefined}) 
WriteResult({ "nInserted" : 1 }) 
> db.orders.find({item: {$type: 6}}).explain() 
{ 
    "queryPlanner" : { 
     "plannerVersion" : 1, 
     "namespace" : "temp.orders", 
     "indexFilterSet" : false, 
     "parsedQuery" : { 
      "item" : { 
       "$type" : 6 
      } 
     }, 
     "winningPlan" : { 
      "stage" : "FETCH", 
      "filter" : { 
       "item" : { 
        "$type" : 6 
       } 
      }, 
      "inputStage" : { 
       "stage" : "IXSCAN", 
       "keyPattern" : { 
        "item" : 1 
       }, 
       "indexName" : "item_1", 
       "isMultiKey" : false, 
       "isUnique" : false, 
       "isSparse" : false, 
       "isPartial" : false, 
       "indexVersion" : 1, 
       "direction" : "forward", 
       "indexBounds" : { 
        "item" : [ 
         "[undefined, undefined]" 
        ] 
       } 
      } 
     }, 
     "rejectedPlans" : [ ] 
    }, 
    "serverInfo" : { 
     "host" : "Andys-MacBook-Pro-2.local", 
     "port" : 27017, 
     "version" : "3.2.8", 
     "gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0" 
    }, 
    "ok" : 1 
} 

回答

1

爲空平等匹配謂詞的語義(如{"a.b": null})是複雜的不夠,因爲現場可能包含僅索引掃描不足以提供正確結果的子文檔。

根據https://jira.mongodb.org/browse/SERVER-18653?focusedCommentId=931817&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-931817

的服務器版本2.6.0改變空平等 匹配謂詞的語義,使得文檔{A:[]}不再 視爲匹配爲查詢謂詞{「ab」:null}(在之前的 版本的服務器中,這個文檔被認爲是與這個謂詞相匹配的謂詞)。這是在2.6兼容性說明中記錄的,在 下的「空比較」部分。

對於具有密鑰模式{「a.b」:1}的索引,此文檔{a:[]} 生成索引鍵{「」:null}。其他文檔(如{a:null}和 )也會生成索引鍵{「」:null}。作爲 結果,如果謂詞{「a.b」:null}的查詢使用此索引,那麼 查詢系統無法從索引關鍵字{「」:null}中判斷是否或關聯文檔與謂詞匹配。因此,分配了INEXACT_FETCH範圍而不是EXACT範圍,因此 FETCH階段被添加到查詢執行樹中。

附加說明:

  1. 文檔{}生成索引鍵{ 「」:空}用於與鑰匙圖案索引{ 「A·B」:1}。
  2. 文檔{a:[]}也爲密鑰模式爲{「a.b」:1}的索引生成索引鍵{「」:null}。
  3. 文檔{}匹配查詢{「a.b」:null}。
  4. 文檔{a:[]}與查詢{「a.b」:null}不匹配。

因此,查詢{「AB」:空}由與鍵 圖案{「AB」:1}的索引回答必須獲取文檔並重新檢查謂詞, 爲了確保文檔{}包含在結果集 中,並且文檔{a:[]}不包含在結果集中。