基於歷史的優化 (HBO)

HBO 是一個框架,可讓您記錄查詢的統計資料,以將這些統計資料重複用於具有相似計畫的未來查詢。為了將查詢與相似的計畫進行比對,會將查詢計畫正規化,以消除計畫之間不相關的差異 (例如,計畫中中間變數的命名),並且會將每個計畫節點雜湊為字串值。與相同雜湊值相關聯的歷史統計資料會用於 HBO 中。HBO 統計資料優先於成本模型的估計。當歷史統計資料不可用時,最佳化器會回復為基於成本的統計資料。為 HBO 記錄的統計資料位於 PlanStatistics 結構中,其中包含

欄位

說明

最佳化器

rowCount

計畫節點輸出的列數

DetermineJoinDistributionType DetermineSemiJoinDistributionType PushPartialAggregationThroughExchange

outputSize

計畫節點輸出的資料大小

DetermineJoinDistributionType DetermineSemiJoinDistributionType PushPartialAggregationThroughExchange

joinNodeStatistics

包括探測和建置輸入的輸入列總數和具有 NULL 連接鍵的列數

RandomizeNullKeyInOuterJoin

tableWriterNodeStatistics

表格寫入器中的任務數

ScaledWriterRule

partialAggregationStatistics

部分彙總節點的輸入和輸出列數和大小

PushPartialAggregationThroughExchange

如何使用 HBO

Presto 支援在查詢最佳化中使用歷史統計資料。在 HBO 中,會儲存目前查詢的統計資料,並可用於最佳化未來的查詢。Redis HBO 提供者可用作歷史統計資料的儲存。HBO 由下列組態屬性和工作階段屬性控制

組態屬性

下列組態屬性可用於 HBO

組態屬性名稱

說明

預設值

optimizer.use-history-based-plan-statistics

使用歷史統計資料進行查詢最佳化。

False

optimizer.track-history-based-plan-statistics

記錄目前查詢的統計資料作為歷史統計資料,以供未來查詢使用。

False

optimizer.track-history-stats-from-failed-queries

從失敗查詢中追蹤完整計畫片段的基於歷史的計畫統計資料。

True

optimizer.history-based-optimizer-timeout

基於歷史的最佳化器的逾時。

10

optimizer.enforce-timeout-for-hbo-query-registration

強制執行 HBO 最佳化器中查詢註冊的逾時

False

optimizer.treat-low-confidence-zero-estimation-as-unknown

在聯結期間,將 LOW 信賴度、零估計值視為 UNKNOWN

False

optimizer.confidence-based-broadcast

根據所使用統計資料的信賴度進行廣播,方法是廣播具有最高信賴度統計資料的 joinNode 端。如果信賴度相同,則會遵循原始行為。

False

optimizer.retry-query-with-history-based-optimization

如果 HBO 可以協助變更現有的查詢計畫,則自動重試失敗的查詢

False

hbo.history-matching-threshold

當目前表格和歷史表格之間的大小差異超過此閾值時,請勿比對歷史統計資料。當值為 0.0 時,只有當兩者的大小完全相同時,才比對歷史統計資料。

0.1

hbo.max-last-runs-history

儲存歷史統計資料的最後執行次數。

10

工作階段屬性

工作階段屬性會設定在指定工作階段中執行的查詢的行為變更。設定時,它們會覆寫目前工作階段中對應的組態屬性 (如果有的值)。

工作階段屬性名稱

說明

預設值

use_history_based_plan_statistics

覆寫目前工作階段中組態屬性 optimizer.use-history-based-plan-statistics 的行為。

optimizer.use-history-based-plan-statistics

track_history_based_plan_statistics

覆寫目前工作階段中組態屬性 optimizer.track-history-based-plan-statistics 的行為。

optimizer.track-history-based-plan-statistics

track_history_stats_from_failed_queries

覆寫目前工作階段中組態屬性 optimizer.track-history-stats-from-failed-queries 的行為。

optimizer.track-history-stats-from-failed-queries

history_based_optimizer_timeout_limit

覆寫目前工作階段中組態屬性 optimizer.history-based-optimizer-timeout 的行為。

optimizer.history-based-optimizer-timeout

enforce_history_based_optimizer_register_timeout

覆寫目前工作階段中組態屬性 optimizer.enforce-timeout-for-hbo-query-registration 的行為。

optimizer.enforce-timeout-for-hbo-query-registration

restrict_history_based_optimization_to_complex_query

僅針對複雜查詢 (即具有聯結和彙總的查詢) 啟用基於歷史的最佳化。

True

history_input_table_statistics_matching_threshold

覆寫目前工作階段中組態屬性 hbo.history-matching-threshold 的行為。

hbo.history-matching-threshold

treat-low-confidence-zero-estimation-as-unknown

覆寫目前工作階段中組態屬性 optimizer.treat-low-confidence-zero-estimation-as-unknown 的行為。

optimizer.treat-low-confidence-zero-estimation-as-unknown

confidence-based-broadcast

覆寫目前工作階段中組態屬性 optimizer.confidence-based-broadcast 的行為。

optimizer.confidence-based-broadcast

retry-query-with-history-based-optimization

覆寫目前工作階段中組態屬性 optimizer.retry-query-with-history-based-optimization 的行為。

optimizer.retry-query-with-history-based-optimization

範例

以下顯示使用 HBO 統計資料的查詢計畫範例。對於計畫節點,當統計資料來自 HBO 時,估計統計資料會顯示來源 HistoryBasedSourceInfo

Fragment 1 [HASH]                                                                                                                                            >
    Output layout: [orderpriority, count]                                                                                                                    >
    Output partitioning: SINGLE []                                                                                                                           >
    Stage Execution Strategy: UNGROUPED_EXECUTION                                                                                                            >
    - Project[PlanNodeId 392][projectLocality = LOCAL] => [orderpriority:varchar(15), count:bigint]                                                          >
            Estimates: {source: HistoryBasedSourceInfo, rows: 5 (117B), cpu: ?, memory: ?, network: ?}                                                       >
        - Aggregate(FINAL)[orderpriority][$hashvalue][PlanNodeId 4] => [orderpriority:varchar(15), $hashvalue:bigint, count:bigint]                          >
                Estimates: {source: HistoryBasedSourceInfo, rows: 5 (117B), cpu: ?, memory: ?, network: ?}                                                   >
                count := "presto.default.count"((count_8)) (1:50)                                                                                            >
            - LocalExchange[PlanNodeId 354][HASH][$hashvalue] (orderpriority) => [orderpriority:varchar(15), count_8:bigint, $hashvalue:bigint]              >
                - RemoteSource[2] => [orderpriority:varchar(15), count_8:bigint, $hashvalue_9:bigint]

使用 HBO 的最佳化

DetermineJoinDistributionType 和 DetermineSemiJoinDistributionType

這兩個最佳化決定是否對聯結執行廣播或重新分割。它們在最佳化中使用探測和建置輸入的大小。

  • 啟用 HBO 時,會使用從歷史查詢記錄的資料大小。

  • 當 HBO 統計資料不可用或 HBO 已停用時,會使用來自成本模型的統計資料。

ReorderJoins

此最佳化會根據輸入和輸出的大小,重新排序聯結順序。啟用 HBO 時,會使用從歷史查詢記錄的資料大小。

PushPartialAggregationThroughExchange

此最佳化會決定是否將彙總分割為部分彙總和最終彙總。

  • track_partial_aggregation_history 設定為 true,以追蹤部分彙總節點的輸出大小。

  • 設定 use_partial_aggregation_history 為 true,以使用部分聚合節點統計資訊來決定是否分割聚合。部分聚合統計資訊的追蹤目標是我們在生產查詢中發現的模式,即最終聚合節點會減少基數,但部分聚合不會。當 use_partial_aggregation_history 未啟用或部分聚合統計資訊不可用時,它將回退使用最終聚合統計資訊。

注意:當最佳化器停用部分聚合時,沒有關於部分聚合的統計資訊,且部分聚合統計資訊不可用。

ScaledWriterRule

Scaled writer 支援動態增加檔案寫入任務的數量,以避免寫出過多的小檔案。預設情況下,它從一個寫入任務開始。在 HBO 中,用於寫入檔案的任務數量會記錄為歷史紀錄。ScaledWriterRule 會根據此資訊決定要從多少個任務開始。它將從 HBO 中記錄的寫入任務數量的一半開始,因為 scaled writer 只會增加寫入任務的數量,如果我們使用與歷史執行完全相同的任務數量,則永遠不會減少。可以透過設定會話屬性 enable_history_based_scaled_writer 來啟用此最佳化。

RandomizeNullKeyInOuterJoin

RandomizeNullKeyInOuterJoin 用於透過將 NULL 鍵重寫為永遠不會匹配的非 NULL 鍵,來減輕外部聯接中 NULL 值的偏斜。它有利於聯接鍵在 NULL 值上存在偏斜的外部聯接查詢。在 HBO 中,會追蹤聯接節點的 NULL 鍵數量和聯接鍵總數;當 NULL 鍵的比例超過以下閾值時,將啟用此最佳化

  • NULL 鍵的數量,硬編碼為 100,000。

  • NULL 鍵的比例,可透過會話屬性 randomize_outer_join_null_key_null_ratio_threshold 設定,預設為 2%。

可以透過將 randomize_outer_join_null_key_strategy 設定為 COST_BASED 來啟用此最佳化。