View a markdown version of this page

僅限索引掃描 (涵蓋的查詢) - Amazon DocumentDB

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

僅限索引掃描 (涵蓋的查詢)

僅索引掃描 (也稱為涵蓋查詢) 是一種最佳化,其中 Amazon DocumentDB 完全從儲存在索引中的欄位回答查詢,而無需讀取基礎文件。由於查詢所需的值已存在於索引中,Amazon DocumentDB 可以略過擷取每個相符的文件,避免讀取完整文件的隨機 I/O 和解碼成本。在查詢計畫中,僅索引掃描會顯示為IXONLYSCAN階段,而不是 IXSCAN(索引掃描) 或 COLLSCAN(集合掃描)。這可減少 I/O,並可大幅降低支援查詢的查詢延遲。

當查詢只接觸單一索引中存在的一小部分欄位時,特別是當文件本身很大時,查詢是純索引掃描的理想候選項目。常見的範例是儀表板、分析彙總和查詢,從更廣泛的複合索引讀取幾個欄位。

無論是否使用僅索引掃描,查詢的結果都相同。只有查詢計畫及其執行的 I/O 數量會變更。

注意

僅索引掃描支援取決於您的 Amazon DocumentDB 引擎版本:

  • 包含多個非_id欄位的涵蓋find投影需要引擎版本 8.0.2 或更新版本。在舊版中,涵蓋的find投影最多可包含一個非_id 欄位。具有兩個或多個欄位的投影會回到正常索引掃描或集合掃描。

  • 純索引掃描是否有彙總管道,例如涵蓋的 $group,需要引擎版本 8.0.2 或更新版本。

當 Amazon DocumentDB 使用僅限索引掃描時

當單一索引包含操作讀取的每個欄位時,Amazon DocumentDB 會考慮下列操作的僅索引掃描。

涵蓋的find投影

當find查詢的投影簡單地包含一或多個頂層欄位,且每個投影欄位都存在於單一索引中時,查詢即符合資格。例如,假設 上有複合索引{ customerId: 1, status: 1, total: 1 },則會涵蓋下列查詢。所有三個投影欄位都存在於索引中,_id並明確排除。(使用多個非_id 欄位覆蓋投影需要引擎版本 8.0.2 或更新版本。)

db.orders.createIndex({ customerId: 1, status: 1, total: 1 }) db.orders.find( { customerId: 42 }, { _id: 0, customerId: 1, status: 1, total: 1 } )

獲勝計劃使用 IXONLYSCAN階段,絕不會從儲存體擷取相符的文件:

{ "stage": "IXONLYSCAN", "indexName": "customerId_1_status_1_total_1", "direction": "forward", "indexCond": { "$and": [ { "customerId": { "$eq": 42 } } ] } }
注意

在涵蓋的find查詢中,結果中的欄位會以索引順序傳回 (欄位在索引定義中出現的順序),而不是在投影中列出的順序或存放在文件中的順序。這符合涵蓋查詢的 MongoDB 行為。由集合掃描回答的查詢會改為以預存文件順序傳回欄位。

涵蓋的$group彙總

$group 階段通常只會讀取幾個欄位 (群組索引鍵及其累積器的輸入),但通常會在沒有前置 的情況下執行$match。如果沒有涵蓋索引,Amazon DocumentDB 會讀取和解碼集合中的每個完整文件,只將這幾個欄位饋送至分組。

引擎版本 8.0.2 和更新版本中提供了彙總管道的索引限定掃描,包括涵蓋的$group階段。

當單一索引包含管道字首讀取的每個欄位時,Amazon DocumentDB 可以將僅索引掃描放在群組下方,並直接從索引讀取這些欄位。考慮將訂單依狀態分組的管道,並加總其總計,並在 上有複合索引{ status: 1, total: 1 }:

db.orders.createIndex({ status: 1, total: 1 }) db.orders.aggregate([ { $group: { _id: "$status", revenue: { $sum: "$total" } } } ])

管道只會讀取 status和 total,兩者都位於索引中,因此會從 饋送群組,IXONLYSCAN而不是集合掃描:

// Without a covering index $group <- COLLSCAN (reads and decodes every full document) // With a covering index on { status, total } $group <- IXONLYSCAN over { status, total } (reads only the referenced fields)

在$group支援 $limit之前領導 $skip、、 $match $sort或 。不過,這些階段參考的每個欄位 (例如$match篩選欄位或$sort索引鍵) 也必須存在於相同的索引中,才能涵蓋管道。如果索引中缺少任何參考欄位,Amazon DocumentDB 會回到集合或索引掃描。

注意

與find投影不同, $group不會隱含包含文件 _id。_id 中的 $group是群組索引鍵,而不是文件識別符,因此索引不需要包含文件_id來涵蓋管道。

涵蓋查詢的需求

若要讓 Amazon DocumentDB 使用僅限索引掃描,必須保留下列所有項目:

  • 單一索引包含查詢讀取的每個欄位。這包括 的投影欄位find,以及群組索引鍵、累積器輸入,以及涵蓋$group管道的任何篩選條件或排序欄位。如果索引中遺失一個欄位,則無法涵蓋查詢。

  • 投影包含最上層欄位 (適用於 find)。排除投影、運算欄位和投影運算子,例如 $slice和 $elemMatch 不符合資格。

  • _id 欄位會計入 (適用於 find)。因為 預設_id包含 ,所以常見的複合索引 { a: 1, b: 1 }不包含 find({}, { a: 1, b: 1 }):隱含 _id 不在索引中。從投影中排除 _id ({ _id: 0, a: 1, b: 1 }) 或_id新增至索引。

  • 索引完全滿足篩選條件。如果 Amazon DocumentDB 無法將部分查詢述詞轉換為索引繫結,則會將該部分保留為剩餘篩選條件、讀取文件以評估它,而且不會將掃描轉換為僅索引掃描。$mod、$ne、 $nin和 等運算子會$exists保留剩餘的篩選條件。

  • 沒有投影欄位是多重索引鍵 (陣列) 資料欄。請參閱 限制。

限制

下列案例無法使用僅索引掃描,並回到正常的索引掃描或集合掃描。這是預期的行為,絕不會影響結果的正確性。

  • 多重索引鍵 (陣列) 欄位。如果欄位曾在任何文件中保留陣列值,則其索引欄為多索引鍵。多索引鍵索引會為每個陣列元素存放一個項目,因此無法從索引重建原始陣列。不會涵蓋讀取此類欄位的任何查詢。

  • 虛線或巢狀路徑。巢狀路徑 上的投影或欄位參考"address.city"不符合資格,即使索引包含該路徑。

  • 排除、計算或運算子投影。{ b: 0 }、 { total: { $add: ["$price", "$tax"] } }或 等投影{ a: { $slice: 5 } }需要完整文件,且不涵蓋在內。

  • 彙總中的完整文件參考。$group 參考整個文件 (例如 { $push: "$$ROOT" }) 的 無法涵蓋,因為沒有任何索引可以重建整個文件。

  • 在 之前重塑階段$group。重塑文件 (例如 $project、$unwind、 $addFields或 $lookup) 的階段,在管道$group不符合涵蓋資格之前出現。

  • 字串述詞上的定序不相符。如果查詢的定序與索引的定序不同,則索引無法提供字串述詞,並留下剩餘篩選條件,強制文件擷取。數值和類型型述詞不受影響。

確認僅限索引掃描

使用explain("executionStats")輸出來確認查詢是由僅索引掃描提供,且不會接觸文件。尋找兩件事:

  • 獲勝計劃使用 IXONLYSCAN階段。

  • 該階段docsExamined的值為 0(且totalDocsExamined為 0),這表示查詢完全從索引中回答,而不讀取任何文件。

db.orders.find( { customerId: 42 }, { _id: 0, customerId: 1, status: 1, total: 1 } ).explain("executionStats").executionStats
{ "executionSuccess": true, "nReturned": "2", "executionTimeMillis": "0.714", "totalDocsExamined": "0", "executionStages": { "stage": "IXONLYSCAN", "nReturned": "2", "indexName": "customerId_1_status_1_total_1", "direction": "forward", "docsExamined": "0" } }
注意

IXONLYSCAN 階段上的非零docsExamined值表示索引包含資料,但 Amazon DocumentDB 仍會檢查儲存體,以確認每個文件版本都可見。當集合最近有已淘汰的文件版本垃圾回收尚未回收的寫入時,可能會發生這種情況。垃圾回收處理這些文件後, 會docsExamined捨棄至 0。此時,查詢會實現涵蓋掃描的完整優點。如需垃圾回收的詳細資訊,請參閱 Amazon DocumentDB 中的垃圾回收。如需關於 docsExamined 指標的詳細資訊,請參閱查詢計畫分析。

最佳實務

  • 設計複合索引,其中包含您最常查詢專案或群組的欄位,因此可以涵蓋這些查詢。

  • _id 從find投影中排除 ({ _id: 0, ... }),除非 _id是覆蓋索引的一部分。

  • 當您想要涵蓋查詢時,請避免索引陣列 (多索引鍵) 欄位,因為多索引鍵資料欄不符合僅索引路徑的資格。

  • 允許垃圾收集與您的寫入工作負載保持同步,讓涵蓋的掃描略過文件存取並docsExamined保持在 0。如需詳細資訊,請參閱Amazon DocumentDB 中的垃圾回收。