建立及管理具名提示

本頁說明如何在 AlloyDB for PostgreSQL 中建立及管理具名提示。

具名提示是查詢與一組提示之間的關聯,可讓您指定查詢計畫的詳細資料。提示會指定查詢偏好的最終執行計畫相關額外資訊。舉例來說,在查詢中掃描資料表時,請使用索引掃描,而非依序掃描等其他類型的掃描。

如要在提示規格內限制最終計畫的選擇,查詢規劃工具會先在產生執行計畫時,將提示套用至查詢。之後發出查詢時,系統就會自動套用提示。 這種做法可讓您從規劃工具強制執行不同的查詢計畫。舉例來說,您可以使用提示,強制對特定資料表執行索引掃描,或強制在多個資料表之間使用特定聯結順序。

AlloyDB 具名提示支援開放原始碼 pg_hint_plan 擴充功能的所有提示。

此外,AlloyDB 支援下列直欄引擎提示:

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

AlloyDB 可讓您為參數化查詢和非參數化查詢建立具名提示。在本頁中,非參數化查詢稱為「參數敏感查詢」

工作流程

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

  1. 找出要建立具名提示的查詢
  2. 建立具名提示,內含下次執行查詢時要套用的提示。
  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」。

  • 如要在資料庫中使用具名提示,請以 alloydbsuperuserpostgres 使用者身分,在 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 (選用):您要建立具名提示的查詢 ID。

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

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

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

  • 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 的具名提示。規劃工具會套用提示 IndexScan(t),在下次執行這個範例查詢時,強制對資料表 t 進行索引掃描。

建立具名提示後,您可以使用 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

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

建立參數感應式具名提示

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

舉例來說,執行下列查詢後,其他查詢 (例如 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

此外,您也可以為非參數化查詢文字建立具名提示,在比對查詢時,查詢文字中的每個常值和常數值都很重要。

套用參數感應式具名提示時,如果兩個查詢只在相應的常值或常數值方面有所不同,系統也會視為不同查詢。如要強制執行這兩項查詢的計畫,您必須為每項查詢分別建立具名提示。不過,您可以為這兩個具名提示使用不同的提示。

如要建立參數感應式命名提示,請將 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」不符。

使用參數感應式命名提示時,請注意下列事項:

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

驗證具名提示的應用程式

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

  • 使用 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

啟用命名提示

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

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

SELECT google_enable_named_hints('my_hint1');

停用具名提示

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

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

SELECT google_disable_named_hints('my_hint1');

刪除已命名的提示

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

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

SELECT google_delete_named_hints('my_hint1');

停用命名提示功能

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

限制

使用具名提示時,有下列限制:

  • 使用查詢 ID 建立具名提示時,原始查詢文字的長度上限為 2048 個字元。
  • 由於複雜查詢的語意,並非所有提示及其組合都能完全套用。建議您先在查詢中測試預期提示,再於正式版中部署具名提示。
  • 強制複雜查詢的聯結順序有其限制。
  • 使用具名提示影響方案選取作業,可能會干擾日後的 AlloyDB 最佳化工具改良作業。請務必在發生下列事件時,重新考慮是否要使用具名提示,並據此調整具名提示:

    • 工作負載出現重大變化。
    • 我們推出或升級了 AlloyDB,其中包含最佳化工具的變更和改良措施。
    • 其他查詢調整方法會套用至相同查詢。
    • 使用具名提示會大幅增加系統效能負擔。

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

後續步驟