要約: GaussDB (MySQL 用) がどのように実行計画をキャッシュし、Prepared Statement のパフォーマンスを高速化するかを見てみましょう。
この記事は、HUAWEI CLOUD コミュニティ「実行プラン キャッシュ、プリペアド ステートメントのパフォーマンス ジャンプの秘密」、作成者: GaussDB データベースから共有されたものです。
序章
データベースシステムでは、SQL(Structured Query Language)文がシステムに入力されると、通常、字句解析(parse)、書き換え(resolve)、最適化(optimize)、実行(execute)というプロセスを経ます。字句構文分析、書き換え、最適化、これら 3 つの段階で SQL ステートメントの実行計画 (プラン) が生成されます。SQL ステートメントに複数の実行プランがある場合、オプティマイザは、多くの実行プランの中から最適と思われるプラン (通常、CPU や IO などを含むシステム リソースの使用量が最も少ないプラン) を最終実行として選択します。計画を実行し、実行者が実行します。実行プランを生成するプロセスは、特に代替の実行プランが多数ある場合に、多くの時間を消費する可能性があります。
図 1: SQL ステートメントの実行
プリペアド ステートメントは、SQL ステートメント内の値をプレースホルダーに置き換えます。これは、テンプレート化された SQL ステートメントまたはパラメーター化された SQL ステートメントと見なすことができます。PREPARE ステートメントが実行されると、従来の MySQL は上図①②のように字句解析を行い、指定されたステートメントを書き換えます。このフェーズはプリコンパイルフェーズと呼ばれます。Prepared Statement の利点は、一度コンパイルして複数回実行することで、プリコンパイル段階に必要な時間を節約できることです。後からEXECUTEコマンドを発行すると、MySQLはコンパイルフェーズ、つまり上図の③で生成された構造を最適化し、対応する実行プランを生成して実行し、出力結果をクライアントに返します。例えば:
PREPARE stmt FROM ‘SELECT * FROM t WHERE t.a = ?’;
SET @var = 2;
EXECUTE stmt USING @var;
従来の MySQL のプリペアド ステートメントは、SQL ステートメントの解析と書き換えに必要な時間を節約するだけですが、SQL ステートメントの場合、記事の冒頭で述べたように、SQL ステートメントの最適化と実行プランの生成には多くのリソースと時間が必要です。 。Prepared Statement ステートメントに対応する最終的な実行計画をキャッシュできれば、EXECUTE ステートメントの実行時に、キャッシュされた実行計画を直接使用できるため、SQL ステートメントの実行計画を生成するプロセス全体をスキップできます。ステートメントの実行パフォーマンスを向上させることができます。この目的を達成するために、GaussDB (MySQL 用) は、Prepared Statement 実行プラン キャッシュ機能を提供します。
次に、GaussDB (MySQL 用) がどのように実行計画をキャッシュし、Prepared Statement のパフォーマンスを高速化するかを見てみましょう。
実行計画キャッシュの仕組み
GaussDB (MySQL 用) のプリペアド ステートメント実行プランのキャッシュの基本原理とプロセスを次の図に示します。
- EXECUTE に応答して、クエリが実行されます。
- is_plan_cached プロセスを使用して、現在のクエリの実行プランがキャッシュされているかどうかを確認します。
- キャッシュされている場合、オプティマイザは現在のクエリ キャッシュ実行プランを初期化し、実行プランのコンテキストに従って実行プランを復元し、復元された実行プランを使用して実行を継続します。
- キャッシュされていない場合は、クエリ最適化を実行して実行プランを生成した後、is_query_cachable プロセスを通じて現在の実行プランがキャッシュできるかどうかを確認します。
- キャッシュ条件が満たされると、実行プランがキャッシュされ (cache_JOIN_plan を呼び出す)、今後の EXECUTE ステートメントはキャッシュされたプランを実行に使用できるようになります。
- キャッシュできない場合は、従来の MySQL 実行プロセス (最適化、実行計画の生成と実行) を通じて EXECUTE ステートメントを実行します。
実行計画のキャッシュ管理
- 実行計画キャッシュ機能スイッチ
GaussDB (MySQL 用) では、Prepared Statement 実行プランのキャッシュ機能を切り替えるための新しいシステム パラメーター rds_plan_cache が導入されました。
rds_plan_cache : このパラメータはON/OFFを設定できます。実行プラン キャッシュの有効化と無効化をそれぞれ表します。このパラメータはセッション/グローバル レベルのパラメータです。
- 実行計画キャッシュの表示
GaussDB (MySQL 用) は、プリペアド ステートメントの実行プランがキャッシュされているかどうか、およびキャッシュされた実行プランが実行中にヒットしたかどうかをユーザーが表示または確認できる 2 つのステータス変数を提供します。
- cached_plan_count:実行プランがキャッシュされているプリペアド ステートメントの数を示します。これはグローバル レベルの状態変数です。
- cached_plan_hits : EXECUTE 実行中にヒットしたキャッシュされた実行プランの数を表示します。これはセッション/グローバル状態です。
Prepared Statement が実行プラン キャッシュ機能をどのように利用するかを例で見てみましょう。
SET @a = 'two';
SET @b = 3;
PREPARE stmt FROM "SELECT * FROM t1 WHERE b = ? AND c = ?";
EXECUTE stmt USING @a,@b;
実行結果は以下の通りです。
a b c
6 two 3
準備されたステートメントを再度実行します。
EXECUTE stmt USING @a,@b;
a b c
6 two 3
準備されたステートメントを 3 回目に実行します。
execute stmt using @a,@b;
a b c
6 two 3
stmt 実行プランがcached_plan_count およびcached_plan_hits によってキャッシュされているかどうか、およびキャッシュされた実行プランが実行中にヒットするかどうかを確認します。
SHOW SESSION STATUS LIKE "cached_plan%";
表示結果は以下の通りです。
Variable_name Value
Cached_plan_count 1
Cached_plan_hits 2
表示された結果から、EXECUTE ステートメントが初めて実行されたときに、Prepared Statement が実行計画をキャッシュしていることがわかります。つまり、Cached_plan_count が 1 であることがわかります。EXECUTE ステートメントを 2 回実行すると、両方とも実行プランのキャッシュなので、Cached_plan_hits が 2 になるまでがわかります。
キャッシュされた実行プランが無効になる仕組み
現在のキャッシュされた実行プランを可能な限り最適な状態に保つために、GaussDB (MySQL 用) は、現在のキャッシュされたプランを無効にし、実行プランを再生成する次のルールを定義します。
- 実行計画に関連するテーブル内のレコード数が、総レコード数の 20% を超えて変化しました。
これは、現在のテーブル内のレコードの 20% を超えるレコードが挿入/削除された場合、現在のキャッシュ プランは無効になり、最適化後に再キャッシュされることを意味します。注: レコード数は統計データに基づいて推定されます。したがって、最初にテーブルを分析することが最善です。 - テーブル定義が変更されました。
たとえば、実行プランに関連するテーブルに対して DDL を実行すると、キャッシュされたプランが無効になり、最適化後に再キャッシュされます。 - システム変数 Optimizer_switch の実行プランの生成に影響を与えるオプションの値が変更された場合、キャッシュされたプランは無効になり、最適化後に再キャッシュされます。
- システム文字セットが変更され、キャッシュされたプランと異なる場合、キャッシュされたプランは無効になり、最適化後に再キャッシュされます。
実行プランのキャッシュ機能の現在の制限事項
GaussDB (MySQL 用) のプリペアド ステートメントの目的は、クエリの最適化時間を節約することです。並列クエリを通じて最適化された大規模なクエリ、つまり比較的大量のデータを含むクエリの場合、これらのクエリの実行時間のほとんどは、実行プランの実行フェーズに集中します。このタイプのクエリの場合、最適化時間は実行時間に比べて無視できるため、GaussDB (MySQL 用) は並列クエリ プランをキャッシュしません。さらに、GaussDB (MySQL 用) は、Prepared ステートメントの実行プランをキャッシュする機能を徐々に強化しており、たとえば、現在は単一テーブルの SELECT クエリ ステートメントのみをサポートしており、当面は UNION 操作をサポートしません。
実行計画キャッシュのパフォーマンス テスト結果
実行プラン キャッシュを使用するシナリオと実行プラン キャッシュを使用しないシナリオについて、Sysbench テスト セットに基づいてパフォーマンス テストの比較を実行しました。テスト結果から、実行プラン キャッシュを有効にすると、パフォーマンスが向上することがわかります。さまざまなサービスが向上します。注: これらのテストは相対的な数値のみを表すものであり、実際のパフォーマンスを表すものではありません。
テスト環境の構成は以下のとおりです。
データセット: 8 テーブル、テーブルあたり 1,000 万行
テスト サーバー: Intel(R) Xeon(R) CPU E5-2690 v4 @ 2.60GHz 2 物理コア 56 プロセッサ 460G メモリ
要約する
GaussDB (MySQL 用) は、実行計画をキャッシュすることで Prepared Statement のパフォーマンスを向上させることができます。特にレンジスキャンのテストセットでは、約2倍のパフォーマンス向上が可能です。将来的には、さらに多くのクエリ シナリオがサポートされる予定であり、パフォーマンスの高速化に期待する価値があります。
クリックしてフォローして、Huawei Cloudの最新テクノロジーについて初めて学びましょう~