基於歷史的優化 (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
組態屬性名稱 |
說明 |
預設值 |
---|---|---|
|
使用歷史統計資料進行查詢最佳化。 |
|
|
記錄目前查詢的統計資料作為歷史統計資料,以供未來查詢使用。 |
|
|
從失敗查詢中追蹤完整計畫片段的基於歷史的計畫統計資料。 |
|
|
基於歷史的最佳化器的逾時。 |
|
|
強制執行 HBO 最佳化器中查詢註冊的逾時 |
|
|
在聯結期間,將 |
|
|
根據所使用統計資料的信賴度進行廣播,方法是廣播具有最高信賴度統計資料的 joinNode 端。如果信賴度相同,則會遵循原始行為。 |
|
|
如果 HBO 可以協助變更現有的查詢計畫,則自動重試失敗的查詢 |
|
|
當目前表格和歷史表格之間的大小差異超過此閾值時,請勿比對歷史統計資料。當值為 0.0 時,只有當兩者的大小完全相同時,才比對歷史統計資料。 |
|
|
儲存歷史統計資料的最後執行次數。 |
|
工作階段屬性¶
工作階段屬性會設定在指定工作階段中執行的查詢的行為變更。設定時,它們會覆寫目前工作階段中對應的組態屬性 (如果有的值)。
工作階段屬性名稱 |
說明 |
預設值 |
---|---|---|
|
覆寫目前工作階段中組態屬性 |
|
|
覆寫目前工作階段中組態屬性 |
|
|
覆寫目前工作階段中組態屬性 |
|
|
覆寫目前工作階段中組態屬性 |
|
|
覆寫目前工作階段中組態屬性 |
|
|
僅針對複雜查詢 (即具有聯結和彙總的查詢) 啟用基於歷史的最佳化。 |
|
|
覆寫目前工作階段中組態屬性 |
|
|
覆寫目前工作階段中組態屬性 |
|
|
覆寫目前工作階段中組態屬性 |
|
|
覆寫目前工作階段中組態屬性 |
|
範例¶
以下顯示使用 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 來啟用此最佳化。