PolarDB for MySQLは、クエリのパフォーマンスを向上させるために、クエリ内の特定の演算子によって生成された中間結果セットをキャッシュおよび再使用する部分結果キャッシュ (PTRC) 機能を提供します。 このトピックでは、PTRCとは何か、どのように機能するか、およびオプティマイザがそれを使用するかどうかを決定する方法について説明します。
概要
PTRCは、相関サブクエリやネストされたループ結合など、クエリ内の特定の演算子によって生成された中間結果セットをキャッシュします。 キャッシュされた結果は、同じ演算子が再度実行されると再利用されます。
結果キャッシュは、2つの側面で「部分的」です。
PTRCは、クエリ全体の結果セットではなく、クエリ内の特定の演算子の中間結果セットのみをキャッシュします。
PTRCも、これらの特定の演算子のすべての結果セットをキャッシュしません。 キャッシュされた結果セットのスコープは、メモリ制限の対象となります。
従来のクエリキャッシュメカニズムと比較して、PTRCはクエリ全体ではなくサブクエリに対して機能し、PTRCのライフサイクルはクエリが開始および終了すると開始および終了します。 その結果、PTRCは、より多様なシナリオに適している。 PTRCは演算子に対してのみ機能するため、ノード間でクエリを実行してもデータの不整合は発生しません。 PTRCは、次のセクションで説明するように、クエリ内の単一の演算子が特定の要件を満たしている限り有効にできます。 クエリオプティマイザは、コストに基づいてPTRCを使用するかどうかを決定します。
PTRCのしくみ
PTRCは、次の要件を満たしている場合、オペレーターに対して有効にできます。
演算子は相関パラメータに依存し、クエリ内で複数回実行されます。 例としては、ネストされたループ結合と関連サブクエリがあります。
オペレータの相関パラメータは、オペレータが繰り返し実行されても同じままである。 たとえば、演算子には、Random、NOW、UDFなど、結果を変更する関数を含めることはできません。
相関パラメータは、演算子が依存する外部クエリ内のパラメータである。 たとえば、クエリには次の操作が含まれます。t1 JOIN t2 ON t1.a = t2.a
。 この動作では、駆動テーブルであるt1
の各行は、t2
テーブルの行と別々に結合される。 t1.a
は、このネストされたループ結合の相関パラメータである。 t1
にt1.a
と一致する重複値が含まれている場合、PTRCはこれらの値の結果を再利用できます。 別の例では、相関サブクエリでは、サブクエリのすべての実行は、外部クエリの結果に依存し、それは運転パラメータとして使用される。
TPC-H Q17は、PTRCから利益を得ることができるクエリの典型的な例である。
select
sum(l_extendedprice) / 7.0 as avg_yearly
から
lineitem,
部分
ここで
p_partkey = l_partkey
p_brand = 'Brand#34'
p_container = 'MED BOX
and l_quantity < (
選択
0.2 * avg(l_quantity)
から
lineitem
where
l_partkey = p_partkey
);
PTRCは、キーと値のペア形式で結果をキャッシュします。ここで、キーは演算子の相関パラメータであり、値は中間結果です。 この例では、キーはp_partkeyで、値はtrueまたはfalseです。
次の図は、PTRCを含む実行プロセスを示しています。
サブクエリが実行されるたびに、システムはp_partkey
キーがPTRCのキャッシュに存在するかどうかをチェックします。
見つからない場合、サブクエリが実行されます。 結果はキャッシュに追加されます。
見つかった場合、システムはサブクエリを実行せずにキャッシュされた結果を直接使用します。
TPC-H Q17では、part
がlineitem
と結合された後にサブクエリが実行される。 結合結果には、相関パラメーターであるp_partkey
に多数の同じ値が含まれています。 これらのp_partkey
値の結果はPTRCで再利用でき、パフォーマンスが大幅に向上します。
次の図に示すように、EXPLAIN
ステートメントに対して返される実行計画では、サブクエリが実行される前に、Partial result cacheという名前の演算子が表示されます。 これは、PTRC特徴が有効であることを示す。
前提条件
PolarDB for MySQLクラスターはMySQL 8.0を実行し、リビジョンバージョン8.0.2.2.9以降を使用します。 クラスターバージョンの確認方法については、「エンジンバージョン」をご参照ください。
Parameters
パラメーター | レベル | 説明 |
partial_result_cache_enabled | グローバル /セッション | PTRC機能を有効にするかどうかを指定します。 デフォルト値: ON。 有効な値:
|
partial_result_cache_cost_threshold | グローバル /セッション | コストしきい値。 PTRCは、クエリ全体のコストがこのしきい値を超えた場合にのみトリガーされます。 値の値: 0 ~ 18446744073709551615 デフォルト値: 10000。 |
partial_result_cache_check_frequency | グローバル /セッション | 動的フィードバックメカニズムがトリガーされるまでのキャッシュミスの数。 値の値: 0 ~ 18446744073709551615 デフォルト値:200 |
partial_result_cache_low_hit_rate | グローバル /セッション | PTRCを使用するかどうかを決定するヒット率のしきい値。 partial_result_cache_low_hit_rateの値は、partial_result_cache_high_hit_rateの値よりも小さい。 システムは、推定ヒット率がこの値より高い場合にのみPTRCを使用し、クエリの実行中に実際のヒット率がこの値より低くなるとPTRCの使用を停止する。 有効値: 0~100。 デフォルト値は 20 です。 |
partial_result_cache_high_hit_rate | グローバル /セッション | キャッシュをメモリからディスクにダンプするかどうかを決定するヒット率のしきい値。 partial_result_cache_high_hit_rateの値は、partial_result_cache_low_hit_rateの値よりも大きい。 PTRCが使用するメモリの最大量に達し、ヒット率がこの値よりも高い場合、キャッシュされた結果はメモリからディスクにダンプされ、新しいキャッシュがディスクに格納されます。 有効値: 0~100。 デフォルト値: 70。 |
partial_result_cache_max_mem_size | グローバル /セッション | 1つのクエリでPTRCが使用できるメモリの最大量。 値の値: 0 ~ 18446744073709551615 単位:バイト デフォルト値: 67108864 |
オプティマイザがPTRCを使用するかどうかを判断する方法
PTRCは、有効なときにシステムリソースを消費します。 たとえば、演算子が実行されるたびにキャッシュされた結果をチェックし、キャッシュされた結果はメモリスペースを占有します。 したがって、PTRCはすべてのクエリに適しているわけではありません。
クエリにPTRCを使用するかどうかは、オプティマイザが決定します。 次のパラメータが考慮されます。
partial_result_cache_cost_threshold
partial_result_cache_low_hit_rate
partial_result_cache_cost_threshold
が優先されます。
クエリの全体的なコストがこのしきい値よりも低い場合、オプティマイザはこのクエリを、それ自体が些細な実行コストを招く短いクエリと見なします。 この場合、PTRCはパフォーマンスをわずかに向上させるか、キャッシュチェックのために応答速度を低下させることさえあります。
クエリの全体的なコストがこのしきい値よりも高い場合、オプティマイザはすべての演算子をトラバースしてPTRC要件を満たす演算子を見つけ、修飾演算子のヒット率を推定します。
hit_rate = (fanout - ndv)/fanout
fanout
は、演算子が実行された合計回数を示します。ndv
は、相関パラメータ (キー) のユニークな値の数を示します。
hit_rate
がpartial_result_cache_low_hit_rate
値より低い場合、PTRCは演算子に使用されません。 しかしながら、推定は常に機能するとは限らない。 MySQLでは、コストはインデックスまたはヒストグラムに基づいて推定されます。 相関パラメータの列にインデックスやヒストグラムがない場合、ndv
を正確に推定できません。 この場合、オプティマイザは、コストを見積もることなく、クエリのPTRCを有効にします。 動的フィードバック機構は、クエリの実行中に、PTRCを使用し続けるかどうかを決定する。
PTRCの動的フィードバックメカニズム
クエリの実行中、システムはPTRCのヒット率とメモリ使用量を監視し、機能の使用を継続するかどうかを判断します。 これが動的フィードバック機構である。 PTRCを有効にすると、システムは各キャッシュチェックの情報を収集し、その情報に基づいて定期的にヒット率を計算します。 ヒット率がpartial_result_cache_low_hit_rate
値よりも低くなると、パフォーマンスのオーバーヘッドを減らすために残りの実行でPTRCが無効になります。
partial_result_cache_check_frequency
パラメーターは、ヒット率の計算頻度を指定します。 例えば、デフォルト値200が使用される場合、ヒット率は、200のキャッシュミス毎に計算される。
システムはまた、PTRCキャッシュによって使用されるメモリの量が閾値に達したときにヒット率を計算する。 この場合、システムは、キャッシュを削除するか、またはキャッシュをディスクにダンプすることもできる。
メモリ制限を超えたときのメカニズムの説明:
hit_rate
がpartial_result_cache_low_hit_rate
より低い場合、PTRCは無効になります。hit_rate
がpartial_result_cache_high_rate
より高い場合、メモリに格納されているキャッシュはディスクにダンプされます。 ストレージメディアの変更は、パフォーマンス向上を大幅に低下させません。hit_rate
が2つのしきい値の間にある場合、LRU (Least Recently Used) メカニズムが有効になります。 システムは、ヒット率要件を満たさないキャッシュを削除し、新しいデータをキャッシュします。 新しいキャッシュが再び過剰なメモリ使用を引き起こす場合、動的フィードバック機構が再びトリガされる。
メモリ制限は、partial_result_cache_max_mem_size
パラメーターで指定します。 クエリでのPTRCのメモリ使用量がこの制限を超えると、クエリでPTRCが有効になっているすべての演算子に対して動的フィードバックメカニズムがトリガーされます。
パフォーマンステスト
以下の要因がPTRCの影響に影響します。
PTRCが使用されるオペレーターのコスト。 コストが高いほど、パフォーマンスの向上が大きくなります。 コストが低い場合、PTRCはわずかなパフォーマンス改善のみを実現します。
キャッシュヒット率。 ヒット率が高いほど、パフォーマンスの向上が大きくなります。
このテストでは、TPC-H Q17の次のサブクエリにPTRCが使用されます。
PTRCが有効なクエリの実行プラン。
TPCH-Q17、キャッシュヒット率は96% である。 次の図に示すように、PTRCによってパフォーマンスが大幅に向上します。
概要
PTRCは、相関パラメータに依存する複雑な演算子を持つクエリ用に設計されています。 中間結果セットをキャッシュして再使用し、計算の繰り返しを減らします。 ヒット率が高い場合、PTRCは大幅なパフォーマンス改善をもたらすことができます。 PTRCが適切な演算子には、相関するサブクエリとネストされたループ結合 (内部結合、外部結合、半結合、および逆結合) が含まれます。