您可以使用PolarDB MySQL版提供的Auto Plan Cache功能,來緩存SQL語句的執行計劃信息,以縮短查詢優化時間,提升SQL語句的查詢性能。本文介紹了Auto Plan Cache功能的背景信息、前提條件、依賴的參數和接口等內容。
背景信息
執行計劃的選擇需要考慮諸多因素,如統計信息、不同的連接順序和不同的查詢變換等。對于不同的查詢語句,其優化時間不同,可能會存在某些SQL語句的查詢優化時間在整體執行時間中占比很大的情況。如果這類SQL語句執行的次數較多,就會因為優化時間占比大導致系統負載增加。通過緩存并復用SQL語句的執行計劃,可以減少每次執行SQL語句的優化時間,從而提升查詢性能,降低數據庫負載,提升吞吐能力。
除此之外,還有很多查詢語句的查詢優化時間占比很小,執行時間受執行計劃的影響非常大,SQL語句中不同參數值對應不同的最優執行計劃。某些場景下,MySQL會根據參數值從引擎獲取實際數據做進一步優化。
上述兩類查詢一旦固定執行計劃,查詢響應時間和負載開銷不會有明顯優化,反而可能使查詢性能回退。
為了提升優化時間占比太多的SQL語句的查詢性能,降低系統負載,同時避免執行SQL語句時因采用固定執行計劃而導致查詢性能回退問題。PolarDB MySQL版提供了Auto Plan Cache功能。Auto Plan Cache功能提供了AUTO、DEMAND和ENFORCE三種模式,您可以根據需要將loose_plan_cache_type
參數設置為三種模式中的任意一種模式,將SQL語句的執行計劃緩存在Plan Cache中,以減少執行查詢語句時的優化時間,提升查詢性能。當緩存在Plan Cache中的執行計劃涉及的表的統計信息發生變化,或對緩存中執行計劃引用的表執行了DDL操作時,緩存的執行計劃會自動失效。
前提條件
PolarDB集群版本需滿足以下條件之一:
PolarDB MySQL版8.0.1版本且修訂版本為8.0.1.1.33及以上。
PolarDB MySQL版8.0.2版本且修訂版本為8.0.2.2.12及以上。
參數說明
您可以在PolarDB控制臺上設置下表中的參數,詳細操作步驟請參見設置集群參數和節點參數。
參數 | 說明 |
loose_plan_cache_type | Auto Plan Cache模式。取值如下:
|
loose_plan_cache_expire_time | Plan Cache中的執行計劃超過該時間沒有被命中,內存會被回收。單位為秒。 取值范圍:0~UINT_MAX。默認值為1800。 |
loose_auto_plan_cache_pct_threshold | 優化時間占語句整體執行時間的百分比閾值。 取值范圍:0~100。默認值為20。 |
loose_auto_plan_cache_time_threshold | SQL語句整體執行時間閾值。單位為微秒。 取值范圍:0~ULONG_MAX。默認值為400。 |
loose_auto_plan_cache_count_threshold | 當 取值范圍:0~ULONG_MAX。默認值為512。 說明 當緩存到Plan Cache中的次數閾值大于或等于 |
接口說明
dbms_sql.add_plan_cache(schema, query)
:將指定SQL語句的執行計劃緩存到Plan Cache中。當
loose_plan_cache_type
參數配置為DEMAND時,您可以通過該內置存儲過程將指定SQL語句的執行計劃緩存到Plan Cache中。示例如下:CALL dbms_sql.add_plan_cache("test", "SELECT * FROM t_for_plan WHERE c1 > 1 AND c1 < 10");
上述語句執行完成后,當您執行的SQL語句滿足
SELECT * FROM t_for_plan WHERE c1 > ? AND c1 < ?
模板時,該SQL語句的執行計劃會被緩存到Plan Cache中。dbms_sql.display_plan_cache_table()
:查看當前Plan Cache中引用的表信息。示例如下:CALL dbms_sql.display_plan_cache_table()\G
執行結果如下:
*************************** 1. row *************************** SCHEMA_NAME: test TABLE_NAME: t_for_plan REF_COUNT: 1 VERSION: 0 VERSION_TIME: 2023-03-10 17:21:35.605264
對應的參數說明如下:
SCHEMA_NAME:引用的表所在的SCHEMA名稱。
TABLE_NAME:引用的表名。
REF_COUNT:引用的表在Plan Cache中被引用的數量。
VERSION:引用的表在Plan Cache中的版本。
VERSION_TIME:引用當前版本的表的時間。
dbms_sql.delete_sharing_by_rowid(row_id)
:刪除指定SQL語句的執行計劃。row_id
為存儲在mysql.sql_sharing
表中的執行計劃的行ID值。示例
執行以下命令,查看緩存中的執行計劃信息。
SELECT Id, Schema_name, Type, Digest_text FROM mysql.sql_sharing WHERE Type = 'PLAN_CACHE'\G
查詢結果如下:
*************************** 1. row *************************** Id: 1 Schema_name: test Type: PLAN_CACHE Digest_text: SELECT * FROM `t_for_plan` WHERE `c1` > ? AND `c1` < ?
從以上查詢結果可以看出,
row_id
值為1。刪除上述查詢中的執行計劃。
CALL dbms_sql.delete_sharing_by_rowid(1);
獲取Plan Cache中的緩存信息
SQL語句的執行計劃存儲在SQL Sharing模塊中,您可以通過以下SQL語句在INFORMATION_SCHEMA.SQL_SHARING
表中查詢Plan Cache中的緩存信息。
SELECT TYPE, REF_BY, SQL_ID, SCHEMA_NAME, DIGEST_TEXT, PLAN_ID, PLAN, PLAN_EXTRA, EXTRA FROM INFORMATION_SCHEMA.SQL_SHARING WHERE json_contains(REF_BY, '"PLAN_CACHE"') or json_contains(REF_BY, '"PLAN_CACHE(DEMAND)"')\G
示例
數據準備。
CREATE TABLE t_for_plan AS WITH RECURSIVE t(c1, c2, c3) AS (SELECT 1, 1, 1 UNION ALL SELECT c1+1, c1 % 50, c1 %200 FROM t WHERE c1 < 1000) SELECT c1, c2, c3 FROM t; CREATE INDEX i_c1_c2 on t_for_plan(c1, c2);
將Auto Plan Cache模式設置為DEMAND。
您可以通過以下兩種方式來設置Auto Plan Cache模式。
在PolarDB控制臺的參數配置頁面將
loose_plan_cache_type
參數設置為DEMAND。設置完成后,斷開當前連接并重新連接數據庫。在當前數據庫連接中執行以下命令,將當前會話中的
plan_cache_type
參數設置為demand
。SET plan_cache_type=demand;
執行以下命令,將指定SQL語句的執行計劃緩存到Plan Cache中。
CALL dbms_sql.add_plan_cache("test", "SELECT * FROM t_for_plan WHERE c1 > 1 AND c1 < 10");
執行查詢語句。
SELECT * FROM t_for_plan WHERE c1 > 1 AND c1 < 10;
查詢Plan Cache中的緩存信息。
SELECT TYPE, REF_BY, SQL_ID, SCHEMA_NAME, DIGEST_TEXT, PLAN_ID, PLAN, PLAN_EXTRA, EXTRA FROM INFORMATION_SCHEMA.SQL_SHARING WHERE json_contains(REF_BY, '"PLAN_CACHE"') or json_contains(REF_BY, '"PLAN_CACHE(DEMAND)"')\G
查詢結果如下:
*************************** 1. row *************************** TYPE: SQL REF_BY: ["PLAN_CACHE(DEMAND)"] SQL_ID: 9jrvksr3wjux6 SCHEMA_NAME: test DIGEST_TEXT: SELECT * FROM `t_for_plan` WHERE `c1` > ? AND `c1` < ? PLAN_ID: NULL PLAN: NULL PLAN_EXTRA: NULL EXTRA: {"TRACE_ROW_ID":1} *************************** 2. row *************************** TYPE: PLAN REF_BY: ["PLAN_CACHE"] SQL_ID: 9jrvksr3wjux6 SCHEMA_NAME: test DIGEST_TEXT: NULL PLAN_ID: 08xftakma6pm6 PLAN: /*+ INDEX(`t_for_plan`@`select#1` `i_c1_c2`) */ PLAN_EXTRA: {"access_type":["`t_for_plan`:range"]} EXTRA: {"PLAN_CACHE_INFO":{"tables":[`test`.`t_for_plan`], "versions":[0], "hits": 0}}
其中,
EXTRA
字段的PLAN_CACHE_INFO
中會展示引用的表、引用的表的版本和執行計劃命中次數。
查詢性能
在集群規格為8核32 GB,數據庫中已創建25張表,單張表存儲400萬行數據的場景下進行壓測。壓測使用的SQL語句為:SELECT id FROM sbtestN WHERE k IN(...)
,其中,IN LIST的長度為20。在PS協議和非PS協議下,測試loose_plan_cache_type
參數配置為OFF、AUTO和ENFORCE時的性能。測試結果如下:
PS協議下的性能測試結果如下:
非PS協議下的性能測試結果如下:
從以上測試結果可以看出:Auto Plan Cache功能在PS協議和非PS協議下都能夠獲得50%以上的性能提升。