Mongodb

解釋輸出中的 DISTINCT_SCAN 和 IXSCAN 有什麼區別?

  • March 11, 2022

在 Mongo 3.4explain("executionStats").distinct(...)中,對於某些查詢,獲勝計劃包含一個IXSCAN步驟,而對於其他查詢,它包含一個DISTINCT_SCAN步驟。

兩者有什麼區別?其中一個比另一個快嗎?

它們是用於不同目的的不同階段。我相信DISTINCT_SCAN只有在欄位中有索引時才會出現。一個IXSCAN階段基本上意味著查詢計劃器將索引掃描為階段之一。

例如:

> db.test.createIndex({a:1})
{
 "createdCollectionAutomatically": true,
 "numIndexesBefore": 1,
 "numIndexesAfter": 2,
 "ok": 1
}

對索引欄位執行find()操作將觸發IXSCAN階段的存在:

> db.test.explain().find({a:1})
{
 ...
   "winningPlan": {
     "stage": "FETCH",
     "inputStage": {
       "stage": "IXSCAN",
       "keyPattern": {
         "a": 1
       },
       "indexName": "a_1",
       ...

distinct()索引欄位上執行時會觸發DISTINCT_SCAN階段:

> db.test.explain().distinct('a')
{
 ...
   "winningPlan": {
     "stage": "PROJECTION",
     "transformBy": {
       "_id": 0,
       "a": 1
     },
     "inputStage": {
       "stage": "DISTINCT_SCAN",
       "keyPattern": {
         "a": 1
       },
       "indexName": "a_1",
       ...

請注意,在這兩種情況下,{a: 1}都會使用索引。如果沒有索引,您將看到一個COLLSCAN階段。

一個並不比另一個“更快”。它們是服務於不同目的的不同階段。

簡而言之:MongoDB DISTINCT_SCAN 是一種特殊的 IXSCAN。 不同之處在於每個索引鍵值只返回一個文件。它有效地跳過過去的重複項,而不是將它們全部包含在內。

例如,假設您插入以下文件:

  • {a:foo, b:10, c:rat}
  • {a:bar, b:1, c:cat}
  • {a:bar, b:2, c:bat}
  • {a:bar, b:1000000, c:mat}

請注意,有很多帶有a=bar.

如果索引被定義為,db.test.createIndex({a:1})那麼該索引的 DISTINCT_SCAN 可用於返回以下內容:

  • {a:foo, b:10, c:rat}
  • {a:bar, b:1, c:cat}``a:bar<–從眾多可用文件中選擇具有值的任意文件。通常這將是索引掃描遇到的第一個。

最初的問題是“哪個更快?” 在所有其他條件相同的情況下,**如果每個索引值有多個文件,則DISTINCT_SCAN 會更快。但是,請記住,索引掃描可以使用 indexBounds 等參數進行配置。因此,使用完全相同索引的兩個 IXSCAN 的執行時間可能會有很大差異,並且相同的可變性適用於 DISTINCT_SCAN 與 IXSCAN 的比較。

在實踐中,我會給出這個建議:

  • DISTINCT_SCAN 和 IXSCAN 都是在查詢計劃中看到的好東西。
  • 查看.explain("executionStats")以查看索引掃描執行的詳細資訊。

引用自:https://dba.stackexchange.com/questions/190740