PolarDB for MySQL の自動プランキャッシュ機能を使用すると、SQL ステートメントの実行計画をキャッシュできます。これにより、クエリの最適化時間が短縮され、クエリパフォーマンスが向上します。このトピックでは、自動プランキャッシュ機能の背景情報、前提条件、パラメーター、およびインターフェイスについて説明します。
背景情報
実行計画の選択には、統計情報、さまざまな結合順序、クエリ変換など、多くの要因が関わります。最適化時間はクエリ文によって異なります。一部の SQL ステートメントでは、クエリの最適化時間が総実行時間のかなりの部分を占めることがあります。これらのステートメントが頻繁に実行されると、長い最適化時間がシステム負荷を増大させます。実行計画をキャッシュして再利用することで、各実行の最適化時間が短縮されます。これにより、クエリパフォーマンスが向上し、データベースの負荷が軽減され、スループット容量が増加します。
他の多くのクエリでは、最適化時間は短いですが、実行時間は実行計画に大きく影響されます。SQL ステートメント内の異なるパラメーター値は、異なる最適な実行計画に対応する可能性があります。一部のシナリオでは、MySQL はさらなる最適化のために、パラメーター値に基づいてエンジンから実際のデータを取得します。
これらのクエリに固定の実行計画を使用しても、クエリ応答時間が改善されたり、負荷のオーバーヘッドが削減されたりするとは限りません。パフォーマンスリグレッションを引き起こすことさえあります。
PolarDB for MySQL は、最適化時間が長い SQL ステートメントのクエリパフォーマンスを向上させ、システム負荷を軽減し、固定の実行計画によるパフォーマンスリグレッションを回避するために、自動プランキャッシュ機能を提供します。自動プランキャッシュ機能には、AUTO、DEMAND、ENFORCE の 3 つのモードがあります。loose_plan_cache_type パラメーターをこれらのモードのいずれかに設定して、プランキャッシュに実行計画をキャッシュできます。これにより、最適化時間が短縮され、クエリパフォーマンスが向上します。キャッシュされた実行計画は、参照されるテーブルの統計情報が変更された場合、または参照されるテーブルに対してデータ定義言語 (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 |
ステートメントの総実行時間に占める最適化時間の割合のしきい値。 有効値: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 ステートメントの実行計画をプランキャッシュにキャッシュします。loose_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 > ? 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 です。例
-
次のコマンドを実行して、キャッシュ内の実行計画情報を表示します。
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);
-
プランキャッシュからのキャッシュ情報の取得
SQL ステートメントの実行計画は、SQL Sharing モジュールに格納されます。次の SQL ステートメントを実行して、INFORMATION_SCHEMA.SQL_SHARING テーブルからプランキャッシュ内のキャッシュ情報をクエリできます。
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 に設定します。
自動プランキャッシュモードは、次の 2 つの方法のいずれかで設定できます。
-
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 リストの長さは 20 でした。パフォーマンスは、プリペアドステートメント (PS) プロトコルと非 PS プロトコルの両方で、loose_plan_cache_type パラメーターを OFF、AUTO、および ENFORCE に設定してテストされました。テスト結果は次のとおりです。
-
PS プロトコルでのパフォーマンス テスト結果:

-
非 PS プロトコルでのパフォーマンス テスト結果:

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