本頁面說明如何在 AlloyDB for PostgreSQL 中建立及管理查詢方案修補程式。
查詢計畫修補程式是查詢與一組提示之間的關聯,可讓您指定查詢計畫的詳細資料。提示會指定查詢偏好的最終執行計畫相關額外資訊。舉例來說,在查詢中掃描資料表時,請使用索引掃描,而非依序掃描等其他類型的掃描。
如要在提示規格內限制最終計畫選項,查詢規劃工具會先將提示套用至查詢,然後產生執行計畫。之後發出查詢時,系統就會自動套用提示。 這種做法可讓您從規劃工具強制執行不同的查詢計畫。舉例來說,您可以使用提示,強制對特定資料表執行索引掃描,或強制在多個資料表之間採用特定聯結順序。
AlloyDB 查詢計畫修補程式支援開放原始碼 pg_hint_plan
擴充功能的所有提示。
此外,AlloyDB 支援下列直欄引擎提示:
ColumnarScan(table)
:強制對資料表執行直欄掃描。NoColumnarScan(table)
:停用資料表上的資料欄掃描。
AlloyDB 可讓您為參數化查詢和非參數化查詢建立計畫修補程式。在本頁中,非參數化查詢稱為「參數敏感查詢」。
工作流程
使用查詢計畫修補程式的步驟如下:
- 找出要建立計畫修補程式的查詢。
- 建立計畫修補程式,其中包含下次執行查詢時要套用的提示。
- 確認已套用計畫修補程式。
本頁面使用下列資料表和索引做為範例:
CREATE TABLE t(a INT, b INT);
CREATE INDEX t_idx1 ON t(a);
DROP EXTENSION IF EXISTS google_auto_hints;
如要繼續使用先前版本建立的查詢計畫修補程式,請按照本頁的說明重新建立。
事前準備
在執行個體上啟用查詢計畫修補功能。將
alloydb.enable_query_plan_patch
標記設為on
。您可以在伺服器或工作階段層級啟用這個旗標。為盡量減少使用這項功能可能造成的額外負擔,請只在工作階段層級啟用這個標記。詳情請參閱「設定執行個體的資料庫旗標」。
如要確認是否已啟用這個標記,請執行
show alloydb.enable_query_plan_patch;
指令。如果啟用旗標,輸出內容會傳回「on」。針對要使用查詢計畫修補程式的每個資料庫,以
alloydbsuperuser
或postgres
使用者身分,在 AlloyDB 主要執行個體的資料庫中建立擴充功能:CREATE EXTENSION google_auto_hints CASCADE;
必要的角色
如要取得建立及管理查詢計畫修補程式所需的權限,請管理員授予下列 Identity and Access Management (IAM) 角色:
根據預設,只有具備 alloydbsuperuser
角色的使用者可以建立計畫修補程式,但您也可以選擇將寫入權限授予資料庫的其他使用者或角色,讓他們也能建立計畫修補程式。
GRANT INSERT,DELETE,UPDATE ON hint_plan.plan_patches, hint_plan.hints TO role_name;
GRANT USAGE ON SEQUENCE hint_plan.hints_id_seq, hint_plan.plan_patches_id_seq TO role_name;
找出查詢
您可以使用查詢 ID 找出需要調整預設計畫的查詢。查詢 ID 至少執行一次後才會顯示。
請使用下列方法找出查詢 ID:
執行
EXPLAIN (VERBOSE)
指令,如以下範例所示:EXPLAIN (VERBOSE) SELECT * FROM t WHERE a = 99; QUERY PLAN ---------------------------------------------------------- Seq Scan on public.t (cost=0.00..38.25 rows=11 width=8) Output: a, b Filter: (t.a = 99) Query Identifier: -6875839275481643436
在輸出內容中,查詢 ID 為
-6875839275481643436
。查詢
pg_stat_statements
檢視區塊。如果您已啟用
pg_stat_statements
擴充功能,可以查詢pg_stat_statements
檢視畫面來找出查詢 ID,如下例所示:select query, queryid from pg_stat_statements;
建立查詢計畫修補程式
如要建立查詢計畫修補程式,請使用 google_create_plan_patch()
函式,在查詢和資料庫中的提示之間建立關聯。
SELECT google_create_plan_patch(
PLAN_PATCH_NAME=>'PLAN_PATCH_NAME',
SQL_ID=>QUERY_ID,
SQL_TEXT=>QUERY_TEXT,
APPLICATION_NAME=>'APPLICATION_NAME',
HINTS=>'HINTS',
DISABLED=>DISABLED);
更改下列內容:
PLAN_PATCH_NAME
:方案修補程式的名稱。這個名稱在資料庫中不得重複。SQL_ID
(選用):您要為其建立計畫修補程式的查詢 ID。您可以使用查詢 ID 或查詢文字 (
SQL_TEXT
參數) 建立方案修補程式。不過,我們建議您使用查詢 ID 建立計畫修補程式,因為 AlloyDB 會根據查詢 ID 自動找出正規化的查詢文字。SQL_TEXT
(選用):您要建立計畫修補程式的查詢文字。使用查詢文字時,文字必須與預期查詢相同,但查詢中的常值和常數值除外。如有任何不符 (包括大小寫差異),可能導致系統無法套用修補程式。如要瞭解如何為含有常值和常數的查詢建立計畫修補程式,請參閱建立參數敏感查詢計畫修補程式。
APPLICATION_NAME
(選用):工作階段名稱,您要使用方案修補程式的用戶端應用程式。空字串可讓您將計畫修補程式套用至查詢,而不論發出查詢的用戶端應用程式為何。HINTS
:以空格分隔的查詢提示清單。DISABLED
(選用):BOOL。如果TRUE
,一開始會建立停用的方案修補程式。
範例:
SELECT google_create_plan_patch(
PLAN_PATCH_NAME=>'my_hint1',
SQL_ID=>-6875839275481643436,
SQL_TEXT=>NULL,
APPLICATION_NAME=>'',
HINTS=>'IndexScan(t)',
DISABLED=>NULL);
這項查詢會建立名為 my_hint1
的企劃書修補程式。規劃工具會套用提示 IndexScan(t)
,在下次執行這個範例查詢時,強制對資料表 t
進行索引掃描。
建立方案修補程式後,您可以使用 google_query_plan_patch_view
確認是否已建立方案修補程式,如下列範例所示:
postgres=>\x
postgres=>select * from google_query_plan_patch_view limit 1;
-[ RECORD 1 ]-----+-----------------------------
plan_patch_name | my_hint1
sql_id | -6875839275481643436
id | 9
query_string | SELECT * FROM t WHERE a = ?;
application_name |
hints | IndexScan(t)
disabled | f
在主要執行個體上建立方案修補程式後,系統會自動將該修補程式套用至唯讀集區執行個體上的相關查詢,前提是您也在唯讀集區執行個體上啟用查詢方案修補程式功能。
建立參數感應查詢計畫修補程式
根據預設,為查詢建立計畫修補程式時,系統會將查詢文字中的任何常值和常數值替換為參數標記 (例如 ?
),藉此將相關聯的查詢文字正規化。即使參數標記的值不同,該正規化查詢也會使用計畫修補程式。
舉例來說,執行下列查詢後,其他查詢 (例如 SELECT * FROM t WHERE a = 99;
) 預設會使用計畫修補程式 my_hint2
。
SELECT google_create_plan_patch(
PLAN_PATCH_NAME=>'my_hint2',
SQL_ID=>NULL,
SQL_TEXT=>'SELECT * FROM t WHERE a = ?;',
APPLICATION_NAME=>'',
HINTS=>'SeqScan(t)',
DISABLED=>NULL);
然後,查詢 (例如 SELECT * FROM t WHERE a = 99;
) 預設可以使用計畫修補程式 my_hint2
。
此外,AlloyDB 也允許您為非參數化查詢文字建立計畫修補程式,其中查詢文字中的每個常值和常數值在比對查詢時都很重要。
套用參數感應式計畫修補程式時,如果兩個查詢只在相應的常值或常數值方面有所不同,也會視為不同。如要強制查詢使用計畫,必須為每個查詢分別建立計畫修補程式。不過,您可以為這兩個計畫修補程式使用不同的提示。
如要建立參數感應式方案修補程式,請將 google_create_plan_patch()
函式的 SENSITIVE_TO_PARAM
參數設為 TRUE
,如下例所示:
SELECT google_create_plan_patch(
PLAN_PATCH_NAME=>'my_hint3',
SQL_ID=>NULL,
SQL_TEXT=>'SELECT * FROM t WHERE a = 88;',
APPLICATION_NAME=>'',
HINTS=>'IndexScan(t)',
DISABLED=>NULL,
SENSITIVE_TO_PARAM=>TRUE);
查詢 SELECT * FROM t WHERE a = 99;
無法使用計畫修補程式 my_hint3
,因為字面值「99」與「88」不符。
使用參數感應式計畫修補程式時,請注意下列事項:
- 參數感應式計畫修補程式不支援查詢文字中的常值、常數值和參數標記。
- 如果您為同一項查詢建立參數感應式計畫修補程式和預設計畫修補程式,系統會優先使用參數感應式計畫修補程式。
- 如要使用查詢 ID 建立參數感應式計畫修補程式,請確認查詢是在目前的工作階段中執行。系統會使用最近一次執行 (在目前工作階段中) 的參數值,建立計畫修補程式。
確認查詢計畫修補程式是否已套用
建立方案修補程式後,請使用下列方法確認查詢方案是否已強制執行。
使用
EXPLAIN
指令或EXPLAIN (ANALYZE)
指令。如要查看規劃工具嘗試套用的提示,您可以在執行
EXPLAIN
指令前,在工作階段層級設定下列旗標:SET pg_hint_plan.debug_print = ON; SET client_min_messages = LOG;
使用
auto_explain
擴充功能。
管理查詢計畫修補程式
您可以在 AlloyDB 中查看、啟用、停用及刪除查詢計畫修補程式。
查看查詢計畫修補
如要查看現有方案修補程式,請使用 google_query_plan_patch_view
函式,如下列範例所示:
postgres=>\x
postgres=>select * from google_query_plan_patch_view limit 1;
-[ RECORD 1 ]-----+-----------------------------
plan_patch_name | my_hint1
sql_id | -6875839275481643436
id | 9
query_string | SELECT * FROM t WHERE a = ?;
application_name |
hints | IndexScan(t)
disabled | f
啟用查詢計畫修補程式
如要啟用現有的計畫修補程式,請使用 google_enable_plan_patch(PLAN_PATCH_NAME)
函式。根據預設,方案修補程式會在您建立方案時啟用。
舉例來說,如要從資料庫重新啟用先前停用的計畫修補程式 my_hint1
,請執行下列函式:
SELECT google_enable_plan_patch('my_hint1');
停用查詢計畫修補
如要停用現有計畫修補程式,請使用 google_disable_plan_patch(PLAN_PATCH_NAME)
函式。
舉例來說,如要從資料庫刪除範例企劃書修補程式 my_hint1
,請執行下列函式:
SELECT google_disable_plan_patch('my_hint1');
刪除查詢計畫修補
如要刪除方案修補程式,請使用 google_delete_plan_patch(PLAN_PATCH_NAME)
函式。
舉例來說,如要從資料庫刪除範例企劃書修補程式 my_hint1
,請執行下列函式:
SELECT google_delete_plan_patch('my_hint1');
停用查詢計畫修補功能
如要在執行個體上停用查詢計畫修補功能,請將 alloydb.enable_query_plan_patch
標記設為 off
。詳情請參閱「設定執行個體的資料庫旗標」。
限制
使用查詢計畫修補程式時,請注意下列限制:
- 使用查詢 ID 建立查詢計畫修補程式時,原始查詢文字的長度限制為 2048 個字元。
- 由於複雜查詢的語意,並非所有提示及其組合都能完全套用。建議您先在查詢中測試預期提示,再將查詢計畫修補程式部署至正式環境。
- 強制複雜查詢的聯結順序有其限制。
使用查詢計畫修補程式影響計畫選取作業,可能會干擾日後的 AlloyDB 最佳化工具改良作業。請務必在發生下列事件時,重新考慮是否要使用查詢計畫修補程式,並據此調整修補程式:
- 工作負載出現重大變化。
- 我們已推出或升級新版 AlloyDB,其中包含最佳化工具的變更和改良措施。
- 其他查詢調整方法會套用至相同查詢。
- 使用查詢計畫修補程式會大幅增加系統效能負擔。
如要進一步瞭解限制,請參閱 pg_hint_plan
說明文件。