建立及管理具名提示

如要控管 AlloyDB for PostgreSQL 查詢規劃工具產生執行計畫的方式,而不修改應用程式查詢,您可以建立、驗證、查看、啟用、停用及刪除具名提示。具名提示會將查詢與一組提示建立關聯,這些提示會指定偏好執行計畫的詳細資料。查詢規劃工具為相關聯的查詢產生執行計畫時,會套用提示,並在後續執行查詢時自動重新套用。舉例來說,您可以使用具名 hint,強制對資料表執行索引掃描,而非依序掃描,或強制多個資料表採用特定 join 順序。

AlloyDB 的具名提示支援開放原始碼 pg_hint_plan 擴充功能的所有提示,以及資料欄引擎的下列提示:

  • ColumnarScan(table):強制對資料表執行資料欄掃描。

  • NoColumnarScan(table):停用資料表的資料欄掃描。

AlloyDB 可讓您為參數化查詢和非參數化查詢建立具名 hint,本文將這些查詢稱為「參數敏感查詢」。

工作流程

使用具名提示的步驟如下:

  1. 找出要建立具名提示的查詢。

  2. 建立具名 hint,並指定下次執行查詢時要套用的提示。

  3. 確認具名提示的應用。

本頁面使用下列資料表和索引做為範例:

CREATE TABLE t(a INT, b INT);
CREATE INDEX t_idx1 ON t(a);
  DROP EXTENSION IF EXISTS google_auto_hints;

如要繼續使用舊版建立的具名提示,請按照本頁的操作說明重新建立。

事前準備

  • 在執行個體啟用具名提示功能。將 alloydb.enable_named_hints 旗標設為 on。您可以在伺服器層級或工作階段層級啟用這個旗標。為盡量減少使用這項功能可能產生的負擔,請僅在工作階段層級啟用這個旗標。

    詳情請參閱「設定執行個體的資料庫旗標」。

    如要確認旗標已啟用,請執行 show alloydb.enable_named_hints; 指令。如果啟用旗標,輸出內容會傳回「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_named_hints() 函式,在資料庫中建立查詢與提示之間的關聯。

SELECT google_create_named_hints(
HINTS_NAME=>'HINTS_NAME',
SQL_ID=>QUERY_ID,
SQL_TEXT=>QUERY_TEXT,
APPLICATION_NAME=>'APPLICATION_NAME',
HINTS=>'HINTS',
DISABLED=>DISABLED);

更改下列內容:

  • HINTS_NAME:具名提示的名稱。在資料庫中不得重複。
  • SQL_ID (選用):要建立具名 hint 的查詢 ID。

    您可以使用查詢 ID 或查詢文字 (SQL_TEXT 參數) 建立具名提示。不過,建議您使用查詢 ID 建立具名提示,因為 AlloyDB 會根據查詢 ID 自動找出正規化查詢文字。

  • SQL_TEXT (選用):要建立具名 hint 的查詢文字。

    使用查詢文字時,文字必須與預期查詢相同,但查詢中的常值和常數值除外。如有任何不符之處 (包括大小寫差異),具名提示可能無法套用。如要瞭解如何為含有常值和常數的查詢建立具名 hint,請參閱「建立參數敏感的具名 hint」。

  • APPLICATION_NAME (選用):要使用具名提示的工作階段用戶端應用程式名稱。如果使用空字串,無論發出查詢的用戶端應用程式為何,都能將具名提示套用至查詢。

  • HINTS:以空格分隔的查詢提示清單。

  • DISABLED (選用):BOOL。如果為 TRUE,一開始建立的具名提示會停用。

範例:

SELECT google_create_named_hints(
HINTS_NAME=>'my_hint1',
SQL_ID=>-6875839275481643436,
SQL_TEXT=>NULL,
APPLICATION_NAME=>'',
HINTS=>'IndexScan(t)',
DISABLED=>NULL);

這項查詢會建立名為 my_hint1 的具名 hint。規劃工具會套用提示 IndexScan(t),在下次執行這個範例查詢時,強制對資料表 t 進行索引掃描。

建立具名 hint 後,您可以使用 google_named_hints_view 確認是否已建立具名 hint,如以下範例所示:

postgres=>\x
postgres=>select * from google_named_hints_view limit 1;
-[ RECORD 1 ]-----+-----------------------------
hints_name | my_hint1
sql_id | -6875839275481643436
id | 9
query_string | SELECT * FROM t WHERE a = ?;
application_name |
hints | IndexScan(t)
disabled | f

在主要執行個體建立具名提示後,只要您也在讀取集區執行個體啟用具名提示功能,系統就會自動將這些提示套用至讀取集區執行個體的相關查詢。

建立參數敏感的具名提示

根據預設,為查詢建立具名 hint 時,系統會將查詢文字中的任何常值和常數值替換為參數標記 (例如 ?),藉此正規化相關聯的查詢文字。即使參數標記的值不同,系統也會對該正規化查詢使用具名提示。

舉例來說,執行下列查詢後,其他查詢 (例如 SELECT * FROM t WHERE a = 99;) 預設會使用具名提示 my_hint2。

SELECT google_create_named_hints(
  HINTS_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 也可讓您為非參數化查詢文字建立具名 hint,其中查詢文字中的每個常值和常數值在比對查詢時都很重要。

套用參數敏感的具名 hint 時,如果兩個查詢只有對應的常值或常數值不同,也會視為不同查詢。如要強制執行這兩項查詢的計畫,必須為每項查詢建立不同的具名提示。不過,您可以為這兩個具名提示使用不同的提示。

如要建立參數敏感的具名提示,請將 google_create_named_hints() 函式的 SENSITIVE_TO_PARAM 參數設為 TRUE,如以下範例所示:

SELECT google_create_named_hints(
HINTS_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」不符。

使用參數敏感的具名提示時,請考量下列事項:

  • 參數敏感的具名 hint 不支援在查詢文字中混合使用常值、常數值和參數標記。
  • 如果您為同一查詢建立參數敏感具名 hint 和預設具名 hint,系統會優先採用參數敏感具名 hint。
  • 如要使用查詢 ID 建立參數敏感的具名 hint,請確認查詢是在目前的工作階段中執行。系統會使用最近一次執行 (在目前工作階段中) 的參數值,建立具名 hint。

確認具名提示的應用

建立具名提示後,請使用下列方法,確認查詢計畫是否已依據提示強制執行。

  • 使用 EXPLAIN 指令或 EXPLAIN (ANALYZE) 指令。

    如要查看規劃工具嘗試套用的提示,您可以在執行 EXPLAIN 指令前,在工作階段層級設定下列旗標:

    SET pg_hint_plan.debug_print = ON;
    SET client_min_messages = LOG;
    
  • 使用 auto_explain 擴充功能。

管理具名提示

AlloyDB 可讓您查看、啟用、停用及刪除具名提示。

查看具名提示

如要查看現有的具名提示,請使用 google_named_hints_view 函式,如以下範例所示:

postgres=>\x
postgres=>select * from google_named_hints_view limit 1;
-[ RECORD 1 ]-----+-----------------------------
hints_name | my_hint1
sql_id | -6875839275481643436
id | 9
query_string | SELECT * FROM t WHERE a = ?;
application_name |
hints | IndexScan(t)
disabled | f

啟用具名提示

如要啟用現有的具名 hint,請使用 google_enable_named_hints(HINTS_NAME) 函式。根據預設,具名提示在建立時會啟用。

舉例來說,如要重新啟用先前從資料庫停用的具名提示 my_hint1,請執行下列函式:

SELECT google_enable_named_hints('my_hint1');

停用具名提示

如要停用現有的具名 hint,請使用 google_disable_named_hints(HINTS_NAME) 函式。

舉例來說,如要從資料庫刪除名為 my_hint1 的範例具名提示,請執行下列函式:

SELECT google_disable_named_hints('my_hint1');

刪除具名提示

如要刪除具名 hint,請使用 google_delete_named_hints(HINTS_NAME) 函式。

舉例來說,如要從資料庫刪除名為 my_hint1 的範例具名提示,請執行下列函式:

SELECT google_delete_named_hints('my_hint1');

停用具名提示功能

如要停用執行個體的具名 hint 功能,請將 alloydb.enable_named_hints 旗標設為 off。詳情請參閱「設定執行個體的資料庫旗標」。

限制

使用具名提示時,須注意下列限制:

  • 使用查詢 ID 建立具名提示時,原始查詢文字的長度上限為 2048 個字元。
  • 由於複雜查詢的語意,並非所有提示和組合都能完整套用。建議您先在查詢中測試預期的提示,再將具名提示部署至正式環境。
  • 強制執行複雜查詢的彙整順序有限制。
  • 使用具名提示影響計畫選擇,可能會干擾日後的 AlloyDB 最佳化工具改善作業。發生下列事件時,請務必重新評估是否要使用具名提示,並據此調整具名提示:

    • 工作負載大幅變動。
    • 新的 AlloyDB 推出或升級版本,包含最佳化工具變更和改善項目。
    • 其他查詢調整方法會套用至相同的查詢。
    • 使用具名提示會大幅增加系統效能負擔。

如要進一步瞭解限制,請參閱 pg_hint_plan 說明文件。

後續步驟