SQL 文の実行計画をキャッシュしてクエリ最適化時間を短縮し、SQL 文のクエリパフォーマンスを向上させるために、PolarDB for MySQL が提供する自動プランキャッシュ機能を使用できます。このトピックでは、自動プランキャッシュ機能について説明します。
背景情報
実行計画の選択は、統計、結合順序、クエリ変換など、多くの要因によって異なります。最適化時間は、クエリ文によって異なります。一部の SQL 文の最適化時間は、全体の実行時間と比較して非常に長くなる場合があります。このような SQL 文が複数回実行されると、最適化時間が長いため、システム負荷が増加します。 SQL 文の実行計画をキャッシュして再利用することで、SQL 文の実行時の最適化時間を短縮できます。これにより、クエリのパフォーマンスが向上し、データベースの負荷が軽減され、スループットが向上します。
対照的に、一部のクエリ文のクエリ最適化時間は非常に短いです。実行時間は、実行計画に大きく依存します。SQL 文のパラメーター値も、最適な実行計画を決定します。シナリオによっては、MySQL はパラメーター値に基づいてエンジンから取得した実際のデータを最適化します。
上記のクエリ文で固定実行計画を使用した場合、クエリの応答時間と負荷のオーバーヘッドは大幅に最適化されません。クエリのパフォーマンスが低下することさえあります。
最適化時間が非常に長い SQL 文のクエリパフォーマンスを向上させ、システム負荷を軽減し、SQL 文の実行時に固定実行計画によって発生するクエリパフォーマンスの低下を回避するために、PolarDB for MySQL は自動プランキャッシュ機能を起動します。自動プランキャッシュ機能は、AUTO、DEMAND、ENFORCE の 3 つのモードをサポートしています。loose_plan_cache_type パラメーターを設定してモードを選択し、プランキャッシュに SQL 文の実行計画をキャッシュして最適化時間を短縮し、クエリパフォーマンスを向上させることができます。プランキャッシュにキャッシュされた実行計画で参照されるテーブルの統計が変更された場合、またはプランキャッシュにキャッシュされた実行計画で参照されるテーブルで DDL 操作が実行された場合、キャッシュされた実行計画は自動的に無効になります。
前提条件
PolarDB クラスタは、次のいずれかのバージョンを使用しています。
PolarDB for MySQL 8.0.1 のクラスタで、リビジョンバージョンが 8.0.1.1.33 以降。
PolarDB for MySQL 8.0.2 のクラスタで、リビジョンバージョンが 8.0.2.2.12 以降。
パラメーター
PolarDBコンソール で、次のパラメーターを設定できます。詳細については、「クラスタとノードのパラメーターを設定する」をご参照ください。
パラメーター | 説明 |
loose_plan_cache_type | 自動プランキャッシュモード。有効な値:
|
loose_plan_cache_expire_time | 実行計画がヒットしない場合にプランキャッシュが再利用されるまでの期間。単位:秒。 有効な値:0 ~ 4294967295。デフォルト値:1800。 |
loose_auto_plan_cache_pct_threshold | SQL 文の最適化時間の全体の実行時間に対する指定比率。 有効な値:0 ~ 100。デフォルト値:20。 |
loose_auto_plan_cache_time_threshold | SQL 文の指定された全体の実行時間。単位:マイクロ秒。 有効な値:0 ~ 18446744073709551615。デフォルト値:400。 |
loose_auto_plan_cache_count_threshold |
有効な値:0 ~ 18446744073709551615。デフォルト値:512。 説明 キャッシュされた実行計画は、実行計画をキャッシュするために許可される操作の数が |
ストアドプロシージャ
dbms_sql.add_plan_cache(schema, query):指定された SQL 文の実行計画をプランキャッシュにキャッシュします。l
oose_plan_cache_typeパラメーターが DEMAND に設定されている場合、この組み込みストアドプロシージャを使用して、指定された SQL 文の実行計画をプランキャッシュにキャッシュできます。例: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 文の実行計画はプランキャッシュにキャッシュされます。dbms_sql.display_plan_cache_table():プランキャッシュで参照されるテーブルに関する情報を表示します。例: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:参照されるテーブルが存在するスキーマの名前。
TABLE_NAME:参照されるテーブルの名前。
REF_COUNT:プランキャッシュ内のテーブルの参照数。
VERSION:プランキャッシュ内の参照されるテーブルのバージョン。
VERSION_TIME:現在のバージョンのテーブルが参照された時刻。
dbms_sql.delete_sharing_by_rowid(row_id):指定された SQL 文の実行計画を削除します。row_id:mysql.sql_sharingテーブルに格納されている実行計画の行 ID 値。例
次の SQL 文を実行して、プランキャッシュにキャッシュされている実行計画をクエリします。
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);
プランキャッシュのクエリ情報
INFORMATION_SCHEMA.SQL_SHARING テーブルから次の SQL 文を実行して、プランキャッシュの情報をクエリできます。
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);自動プランキャッシュモードを DEMAND に設定します。
次のいずれかの方法を使用して、自動プランキャッシュモードを設定できます。
PolarDBコンソール の [パラメーター] ページで、
loose_plan_cache_typeパラメーターを DEMAND に設定します。データベースから切断し、再接続します。現在のデータベース接続を維持し、次の文を実行して、現在のセッションの
plan_cache_typeパラメーターをDEMANDに設定します。SET plan_cache_type=demand;
次の文を実行して、指定された SQL 文の実行計画をプランキャッシュにキャッシュします。
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;プランキャッシュの情報をクエリします。
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 です。 loose_plan_cache_type パラメーターが OFF、AUTO、および ENFORCE に設定されている場合のパフォーマンスを、PS プロトコルと非 PS プロトコルの両方でテストします。テスト結果:
次の図は、PS プロトコルのパフォーマンステスト結果を示しています。

次の図は、非 PS プロトコルのパフォーマンステスト結果を示しています。

テスト結果は、自動プランキャッシュ機能により、PS プロトコルと非 PS プロトコルの両方でパフォーマンスが 50% 以上向上することを示しています。