查詢計劃 - Amazon Redshift

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

查詢計劃

您可以使用查詢計畫來取得運行查詢所需的個別操作的相關資訊。使用查詢計畫之前,建議您先了解 Amazon Redshift 如何處理處理中的查詢和建立查詢計畫。如需詳細資訊,請參閱 查詢計劃和執行工作流程

若要建立查詢計畫,請執行 EXPLAIN 命令,後面接著實際的查詢文字。查詢計畫可提供下列資訊:

  • 執行引擎將執行的操作,請由下至上閱讀結果。

  • 每個操作會執行的步驟類型。

  • 每個操作中使用的資料表和資料欄。

  • 每個操作中處理的資料量,就資料列的數量和資料寬度 (位元組) 而言。

  • 操作的相對成本。成本是一種測量方式,會比較計畫內步驟的相對執行時間。成本不會提供實際執行時間或記憶體消耗的任何精確資訊,也不會提供執行計畫之間有意義的比較。但它可提供您查詢中耗費最多資源的操作的指示。

EXPLAIN 命令不會實際執行查詢。它只會顯示 Amazon Redshift 如果查詢是在目前操作條件下執行時,會執行的計畫。如果您變更資料表的結構描述或資料,並再次執行 ANALYZE 以更新統計資訊中繼資料,查詢計畫可能不同。

EXPLAIN 的查詢計畫輸出為查詢執行的簡化、高階檢視。它不會說明平行查詢處理的詳細資訊。若要查看詳細資訊,請執行查詢本身,然後從 SVL_QUERY_SUMMARY 或 SVL_QUERY_REPORT 檢視取得查詢摘要資訊。如需使用這些檢視的詳細資訊,請參閱分析查詢摘要

下列範例顯示 EVENT 資料表上簡易 GROUP BY 查詢的 EXPLAIN 輸出:

explain select eventname, count(*) from event group by eventname; QUERY PLAN ------------------------------------------------------------------- XN HashAggregate (cost=131.97..133.41 rows=576 width=17) -> XN Seq Scan on event (cost=0.00..87.98 rows=8798 width=17)

EXPLAIN 會傳回每個操作的下列指標:

費用

用在計畫內比較操作的相對值。成本由兩個小數值組成,以兩個句點分隔,例如 cost=131.97..133.41。第一個值,在此情況下的 131.97,提供傳回此操作第一個資料列的相對成本。第二個值,在此情況下的 133.41,提供完成操作的相對成本。當您讀取計劃時,查詢計劃中的成本是累積的,因此HashAggregate成本 (131.97.. 133.41) 包含的 Seq Scan 成本 (0.00.. 87.98) 較它低。

資料列

要傳回的估計資料列數量。在此範例中,掃描預期傳回 8798 個資料列。所以此HashAggregate運算子本身預期會返回 576 個資料列 (在從結果集丟棄重複的事件名稱之後)。

注意

資料列估計是根據 ANALYZE 命令產生的可用統計資料。如果最近未執行 ANALYZE,估計將較不可靠。

寬度

估計的平均資料列寬度 (位元組)。在此範例中,平均資料列的寬度預期為 17 個位元組。

EXPLAIN 運算子

此小節簡要描述您最常在 EXPLAIN 輸出中看見的運算子。如需運算子的完整清單,請參閱 SQL 命令小節中的 EXPLAIN

循序掃描運算子

循序掃描運算子 (Seq Scan) 指出資料表掃描。Seq Scan 會從開頭到結尾循序掃描資料表中的每個資料欄,並評估每個資料列的查詢限制條件 (在 WHERE 子句中)。

聯結運算子

Amazon Redshift 會根據要聯結資料表的實體設計、聯結所需資料的位置,以及查詢本身的特定需求來選取聯結運算子。

  • 巢狀迴路

    最差的最佳聯結,巢狀迴路主要用於交叉聯結 (笛卡兒乘積) 和一些對等聯結中。

  • 雜湊聯結和雜湊

    雜湊聯結和雜湊通常會較巢狀迴路聯結更快速,用於內部聯結和左右外部聯結。當聯結資料表中的聯結資料欄不是散發索引鍵也不是排序索引鍵時,會使用這些運算子。雜湊運算子會為聯結中的內部資料表建立雜湊表;雜湊聯結運算子會讀取外部資料表、雜湊聯結資料欄,並在內部雜湊表中尋找相符項目。

  • 合併聯結

    合併聯結通常是最快速的聯結,用於內部聯結和外部聯結。合併聯結不會用於完整聯結。當聯結資料表中的聯結資料欄為散發索引鍵也是排序索引鍵,並且少於 20% 的聯結資料表未排序時,會使用此運算子。它會依序讀取兩個排序的資料表,並尋找相符的資料列。若要檢視未排序資料列的百分比,請查詢 SVV_TABLE_INFO 系統資料表。

彙整運算子

查詢計畫會在牽涉到彙整函數和 GROUP BY 操作的查詢中使用下列運算子。

  • Aggregate

    純量彙整函數的運算子,例如 AVG 和 SUM。

  • HashAggregate

    未排序的分組彙整函數的運算子。

  • GroupAggregate

    排序的分組彙整函數的運算子。

排序運算子

查詢計畫會在查詢必須排序或合併結果集時使用下列運算子。

  • 排序

    評估 ORDER BY 子句和其他排序操作,例如 UNION 查詢和聯結、SELECT DISTINCT 查詢和視窗函數要求的排序。

  • 合併

    根據衍生自平行操作中繼排序的結果,產生最終排序的結果。

UNION、INTERSECT 和 EXCEPT 運算子

查詢計畫會對牽涉到 UNION、INTERSECT 和 EXCEPT 設定操作的查詢使用下列運算子。

  • Subquery

    用來執行 UNION 查詢。

  • Hash Intersect Distinct

    用來執行 INTERSECT 查詢。

  • SetOp除

    用來執行 EXCEPT (或 MINUS) 查詢。

其他運算子

下列運算子也會經常出現在例行查詢的 EXPLAIN 輸出中。

  • 唯一

    移除複製 SELECT DISTINCT 查詢和 UNION 查詢。

  • 限制

    處理 LIMIT 子句。

  • 視窗

    執行視窗函數。

  • 結果

    執行未牽涉任何資料表存取的純量函數。

  • Subplan

    用於特定子查詢。

  • 網路

    將中繼結果傳送至領導者節點供進一步處理。

  • Materialize

    儲存資料列以輸入至巢狀迴路聯結和一些合併聯結。

EXPLAIN 中的聯結

取決於查詢和基礎資料表的結構,查詢最佳化器會使用不同的聯結類型來擷取資料表資料。EXPLAIN 輸出會參考聯結類型、使用的資料表,以及資料表資料在叢集間配送的方式,以描述查詢的處理方式。

聯結類型範例

下列範例顯示查詢最佳化器可以使用的不同聯結類型。查詢計畫中使用的聯結類型取決於所牽涉資料表的實體設計。

範例:雜湊聯結兩個資料表

下列查詢會聯結 CATID 資料欄上的 EVENT 和 CATEGORY。CATID 為 CATEGORY (但不是 EVENT) 的配送和排序索引鍵。執行雜湊聯結,EVENT 為外部資料表而 CATEGORY 為內部資料表。因為 CATEGORY 為較小的資料表,規劃器會在查詢處理期間透過使用 DS_BCAST_INNER 播送其一份副本至運算節點。此範例中的聯結成本可說明計畫的多數累積成本。

explain select * from category, event where category.catid=event.catid; QUERY PLAN ------------------------------------------------------------------------- XN Hash Join DS_BCAST_INNER (cost=0.14..6600286.07 rows=8798 width=84) Hash Cond: ("outer".catid = "inner".catid) -> XN Seq Scan on event (cost=0.00..87.98 rows=8798 width=35) -> XN Hash (cost=0.11..0.11 rows=11 width=49) -> XN Seq Scan on category (cost=0.00..0.11 rows=11 width=49)
注意

EXPLAIN 輸出中運算子的對應縮排有時會指出那些操作並非彼此相依,因此可以平行開始。在前述範例中,EVENT 資料表上的掃描雖然已與雜湊操作對應,EVENT 掃描仍必須等候雜湊操作已完全完成為止。

範例:合併聯結兩個資料表

下列查詢也使用 SELECT *,但它會聯結 LISTID 資料欄上的 SALES 和 LISTING,其中的 LISTID 已設為這兩個資料表的配送和排序索引鍵。已選擇合併聯結,並且聯結 (DS_DIST_NONE) 不需要重新配送資料。

explain select * from sales, listing where sales.listid = listing.listid; QUERY PLAN ----------------------------------------------------------------------------- XN Merge Join DS_DIST_NONE (cost=0.00..6285.93 rows=172456 width=97) Merge Cond: ("outer".listid = "inner".listid) -> XN Seq Scan on listing (cost=0.00..1924.97 rows=192497 width=44) -> XN Seq Scan on sales (cost=0.00..1724.56 rows=172456 width=53)

下列範例示範相同查詢內不同類型的聯結。在上一個範例中,SALES 和 LISTING 已合併聯結,但第三個資料表 EVENT 必須與合併聯結的結果雜湊聯結。重申,雜湊聯結會衍生播送成本。

explain select * from sales, listing, event where sales.listid = listing.listid and sales.eventid = event.eventid; QUERY PLAN ---------------------------------------------------------------------------- XN Hash Join DS_BCAST_INNER (cost=109.98..3871130276.17 rows=172456 width=132) Hash Cond: ("outer".eventid = "inner".eventid) -> XN Merge Join DS_DIST_NONE (cost=0.00..6285.93 rows=172456 width=97) Merge Cond: ("outer".listid = "inner".listid) -> XN Seq Scan on listing (cost=0.00..1924.97 rows=192497 width=44) -> XN Seq Scan on sales (cost=0.00..1724.56 rows=172456 width=53) -> XN Hash (cost=87.98..87.98 rows=8798 width=35) -> XN Seq Scan on event (cost=0.00..87.98 rows=8798 width=35)

範例:聯結、彙整和排序

下列查詢會執行 SALES 和 EVENT 資料表的雜湊聯結,接着彙整和排序操作以説明分組的 SUM 函數和 ORDER BY 子句。初始的排序運算子會在運算節點上平行執行。然後 Network 運算子會傳送結果至領導者節點,在其中,Merge 運算子會產生最終排序的結果。

explain select eventname, sum(pricepaid) from sales, event where sales.eventid=event.eventid group by eventname order by 2 desc; QUERY PLAN --------------------------------------------------------------------------------- XN Merge (cost=1002815366604.92..1002815366606.36 rows=576 width=27) Merge Key: sum(sales.pricepaid) -> XN Network (cost=1002815366604.92..1002815366606.36 rows=576 width=27) Send to leader -> XN Sort (cost=1002815366604.92..1002815366606.36 rows=576 width=27) Sort Key: sum(sales.pricepaid) -> XN HashAggregate (cost=2815366577.07..2815366578.51 rows=576 width=27) -> XN Hash Join DS_BCAST_INNER (cost=109.98..2815365714.80 rows=172456 width=27) Hash Cond: ("outer".eventid = "inner".eventid) -> XN Seq Scan on sales (cost=0.00..1724.56 rows=172456 width=14) -> XN Hash (cost=87.98..87.98 rows=8798 width=21) -> XN Seq Scan on event (cost=0.00..87.98 rows=8798 width=21)

資料重新分佈

聯結的 EXPLAIN 輸出也可為在叢集間移動資料的方式指定可輔助聯結的方法。資料可以透過播送或重新配送來移動。在播送中,來自聯結一端的資料值會從每個運算節點複製到每個其他運算節點,使得每個運算節點最終有完整的資料副本。在重新配送中,參與的資料值是從其目前的配量傳送至新配量 (可能在不同的節點上)。資料一般會重新配送以符合參與聯結的其他資料表的散發索引鍵 (如果該散發索引鍵是其中一個聯結資料欄)。如果任何資料表都不具備其中一個聯結資料欄上的散發索引鍵,則會配送兩個資料表,或是將內部資料表播送至每個節點。

EXPLAIN 輸出也會參考內部和外部資料表。會先掃描內部資料表,並出現在較接近查詢計畫底端的位置。內部資料表為對其探測相符項目的資料表。它通常位於記憶體中,且通常是雜湊的來源資料表,如有可能,會是要聯結的兩個資料表中較小的那個。外部資料表為要對內部資料表比對的資料列的來源。通常是從磁碟讀取。查詢最佳化器會根據來自 ANALYZE 命令最近一次執行的資料庫統計資料來選擇內部和外部資料表。查詢的 FROM 子句中資料表的順序,並不會決定哪個資料表為內部以及哪個為外部。

請在查詢計畫中使用下列屬性來識別資料將移動的方式,以輔助查詢:

  • DS_BCAST_INNER

    將整個內部資料表的副本播送至所有運算節點。

  • DS_DIST_ALL_NONE

    不需要重新配送,因為已使用 DISTSTYLE ALL 將內部資料表配送至每個節點。

  • DS_DIST_NONE

    不重新配送任何資料表。共置聯結可行,因為會聯結對應的配量,而不需在節點間移動資料。

  • DS_DIST_INNER

    重新配送內部資料表。

  • DS_DIST_OUTER

    重新配送外部資料表。

  • DS_DIST_ALL_INNER

    因為外部資料表使用 DISTSTYLE ALL,會將整個內部資料表重新配送至單一配量。

  • DS_DIST_BOTH

    重新配送這兩個資料表。