Mongodb
解釋輸出中的 DISTINCT_SCAN 和 IXSCAN 有什麼區別?
在 Mongo 3.4
explain("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")
以查看索引掃描執行的詳細資訊。