View a markdown version of this page

Aurora DSQL EXPLAIN 計劃中的批次巢狀迴圈聯結 - Amazon Aurora DSQL

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

Aurora DSQL EXPLAIN 計劃中的批次巢狀迴圈聯結

當查詢將小型外部輸入聯結到 Aurora DSQL 可以從儲存有效率地掃描的內部輸入時,Aurora DSQL 可以選擇Nested Loop (Batched Join)計劃。此聯結類型可在探查內部之前將多個外部資料列分組在一起,以減少運算和儲存層之間的往返。

標準巢狀迴圈一次處理一個外部資料列,並再次為每個資料列執行內部掃描。批次巢狀迴圈聯結會收集一批外部資料列、建置整個批次的內部掃描工作,然後將傳回的內部資料列聯結回相符的外部資料列。

批次巢狀迴圈聯結的運作方式

  1. Aurora DSQL 會從聯結的外部讀取一批資料列。

  2. 如果內部端是 Index Scan或 ,並在外部端Index Only Scan使用Index Cond參數化 ,Aurora DSQL 會繫結每個外部資料列的條件,並將產生的索引掃描金鑰合併為一個批次內部掃描。其他聯結述詞不會驅動內部掃描。

  3. Index Scan 或Index Only Scan沒有外部參數化Index Cond的行為類似於 Full Scan或 Sequential Scan。Aurora DSQL 沒有參數化索引掃描金鑰,可合併每個外部批次執行一次內部掃描,而非每個外部資料列執行一次內部掃描。

  4. Aurora DSQL 會在資料列到達批次時從內部串流資料列。在加入之前,不會具體化批次的整個內部結果。

  5. 當內部 Index Scan或 Index Only Scan具有外部參數化 時Index Cond,Aurora DSQL 會使用 Recheck Cond 將每個傳回的內部資料列比對回批次中適用的外部資料列。Aurora DSQL 接著會套用任何剩餘的聯結述詞。如果沒有外部參數化 Index Cond,Aurora DSQL 會直接套用聯結述詞,因為它會比對每個串流的內部資料列與外部批次。

  6. 對於左側和反聯結,Aurora DSQL 會追蹤哪些外部資料列相符,並在批次的內部掃描完成後發出不相符的資料列。

當內部是具有參數化 的索引掃描時,這種方法最有用Index Cond,因為合併的掃描金鑰提供整個外部批次的目標儲存存取權。

當 Aurora DSQL 使用此聯結時

當聯結的內側是實體掃描節點時,Aurora DSQL 會考慮批次巢狀迴圈聯結,這表示 Index Scan、Full Scan、 Index Only Scan或 Sequential Scan,且批次處理的成本預期低於為每個外部資料列執行內部掃描的成本。實際上,最大效益通常來自較小的外部輸入和內部索引掃描,其外部具有Index Cond參數化。

如果另一個計劃形狀更便宜,例如雜湊聯結或合併聯結,Aurora DSQL 會改為選擇該計劃。若要在調校期間比較計劃形狀,您可以停用目前工作階段的批次巢狀迴圈聯結:

SET dsql.enable_batched_nestloop = off;

如何讀取批次巢狀迴路聯結輸出

下列查詢使用來自 的範例transaction和account資料表讀取 Aurora DSQL EXPLAIN 計劃:

EXPLAIN SELECT t.account_id, a.balance FROM transaction t LEFT JOIN account a ON t.account_id = a.customer_id AND a.balance > CASE WHEN t.description LIKE 'fee%' THEN 0 ELSE 100 END WHERE t.transaction_date >= '2025-01-01' AND (a.status = 'active' OR a.customer_id IS NULL) ORDER BY t.account_id;

EXPLAIN 計劃可以包含類似下列的輸出:

Sort
  Sort Key: t.account_id
  -> Nested Loop (Batched Join)
       Filter: (((status)::text = 'active'::text) OR (customer_id IS NULL))
       Join Type: Left
       Recheck Cond: (customer_id = t.account_id)
       Join Filter: (balance > CASE WHEN (t.description ~~ 'fee%'::text) THEN '0'::numeric ELSE '100'::numeric END)
       -> Full Scan (btree-table) on transaction t
            -> Storage Scan on transaction t
                 Filters: (transaction_date >= '2025-01-01 00:00:00'::timestamp without time zone)
                 -> B-Tree Scan on transaction t
       -> Index Only Scan using idx1 on account a
            Index Cond: (customer_id = t.account_id)
Nested Loop (Batched Join)

顯示 Aurora DSQL 在探測聯結的內側之前,正在批次處理外部資料列。

Index Cond

顯示用來探測目前批次內部的述詞。當內側是 Index Scan或 時Index Only Scan,此述詞通常會參考聯結外側的資料欄。

Filter

顯示套用至聯結結果的條件。在此範例中, WHERE (a.status = 'active' OR a.customer_id IS NULL)條件會顯示在此處。在標準 SQL 左聯結語意下,無法將此條件推送至內部掃描,因為這樣做會變更查詢結果。Aurora DSQL 會在聯結節點上將其顯示為篩選條件。相反地, 上的 條件只會t.transaction_date參考外部資料表,因此會出現在外部實體掃描下方。

Join Type

顯示批次聯結的聯結語意,例如 Left、 Semi或 Anti。

Recheck Cond

只有在內部端是 Index Scan或在聯結的外部Index Only Scan具有至少一個Index Cond參數化的 或 時才會出現。對於每個傳回的內部資料列,Aurora DSQL 會針對批次中的每個外部資料列執行重新檢查,以判斷哪些外部資料列產生該探查,並應該與該內部資料列聯結。

Join Filter

顯示 Aurora DSQL 在將內部資料列比對回批次中的候選外部資料列後評估的聯結述詞。這些述詞會影響哪些資料列對聯結,但它們不會像Index Cond這樣驅動儲存探查。

先前的排序節點

當查詢需要排序輸出時,可能會出現 。批次巢狀迴圈聯結不會保留與標準巢狀迴圈相同的輸出順序保證,因此 Aurora DSQL 可以在傳回最終結果集之前新增明確的排序。