すべてのプロダクト
Search
ドキュメントセンター

PolarDB:部分結果キャッシュ (PTRC)

最終更新日:Jun 22, 2026

PolarDB for MySQL の部分結果キャッシュ (PTRC) 機能を使用すると、クエリ内の演算子からの中間結果セットをキャッシュすることで、クエリのパフォーマンスを向上させることができます。これにより、複雑な演算子の冗長な計算が削減されます。このトピックでは、PTRC の基本概念、仕組み、コストベースの選択、および動的フィードバックメカニズムについて説明します。

基本概念

PTRC は、クエリ内の演算子の結果セットをキャッシュする機能です。たとえば、相関サブクエリやネステッドループ結合などの演算子からの一時的な結果をキャッシュできます。同じ演算子が再度実行された場合、システムは再実行する代わりにキャッシュされた結果を再利用できます。

PTRC の「部分 (Partial)」には、2 つの意味があります。

  • PTRC は、クエリ全体の結果セットではなく、クエリ内の 1 つ以上の演算子の中間結果セットをキャッシュします。

  • 演算子の中間結果セット全体を必ずしもキャッシュするわけではありません。メモリの制限により、結果の一部のみをキャッシュする場合があります。

従来のクエリキャッシュと比較して、PTRC はクエリ内の特定の演算子を高速化することにより、より細かい粒度で動作します。キャッシュはクエリの実行期間中のみ存在します。このアプローチにより、より広い適用性が提供されます。最適化は単一のクエリの内部で行われるため、ノード間のデータ整合性の問題が回避されます。特定の入力パラメーターのセットに対して決定的な結果を生成する場合、どの演算子でも PTRC を使用できます。オプティマイザーはコストに基づいて PTRC を使用するかどうかを決定します。

仕組み

PTRC の中心的な考え方は、演算子の中間結果セットをキャッシュして冗長な実行を回避することです。PTRC は、次の条件を満たす場合に演算子を高速化できます。

  • 演算子が実行に相関パラメーターに依存し、複数回実行されること。例として、ネステッドループ結合や相関サブクエリ演算子が含まれます。

  • 同じ相関パラメーターに対して、演算子の結果が常に同じであること。たとえば、演算子に RANDOM()NOW()、またはユーザー定義関数 (UDF) などの非決定的な関数を含めることはできません。これらを使用すると、最終結果の正確性が損なわれます。

相関パラメーターは、演算子が実行中に依存する外部パラメーターです。たとえば、結合操作 t1 join t2 on t1.a = t2.a で、t1 テーブルが駆動表である場合、t1 テーブルの各行は t2 テーブルと結合されます。この場合、t1.a はネステッドループ結合演算子の相関パラメーターと見なされます。t1 テーブルの t1.a 列に多くの重複する値が含まれている場合、PTRC は冗長な計算を削減できます。別の例は相関サブクエリで、サブクエリの各実行は外部クエリの値に依存します。

TPC-H Q17 クエリは、PTRC の仕組みを説明する良い例です。クエリは次のとおりです。

SELECT
        sum(l_extendedprice) / 7.0 AS avg_yearly
FROM
        lineitem,
        part
WHERE
        p_partkey = l_partkey
        AND p_brand = 'Brand#34'
        AND p_container = 'MED BOX'
        AND l_quantity < (
                SELECT
                        0.2 * avg(l_quantity)
                FROM
                        lineitem
                WHERE
                        l_partkey = p_partkey
        );

PTRC は、演算子の相関パラメーターをキーとして、実行結果を値として使用します。TPC-H Q17 の場合、PTRC キャッシュのフォーマットは、キー = p_partkey、値 = [true/false] となります。

次の図は、TPC-H Q17 の相関サブクエリに対する PTRC の主な実行フローを示しています。image

相関サブクエリが評価されるたびに、システムは p_partkey の値を使用して PTRC キャッシュで結果を検索します。

  • 結果が見つからない場合 (キャッシュミス)、システムはサブクエリを実行し、その結果を PTRC キャッシュに保存します。

  • 結果が見つかった場合 (キャッシュヒット)、システムはキャッシュされた値を直接返し、冗長なサブクエリの実行を回避します。

TPC-H Q17 では、サブクエリは part テーブルと lineitem テーブルが結合された後に実行されます。結合の結果には、サブクエリの相関パラメーターである p_partkey の重複する値が多数含まれています。その結果、PTRC は非常に高いキャッシュヒット率を達成し、大幅なパフォーマンス向上をもたらします。

EXPLAIN コマンドを使用して実行計画を表示できます。サブクエリの前の実行計画に Partial Result Cache 演算子がある場合、PTRC が使用されていることを示します。たとえば、TPC-H Q17 の EXPLAIN の出力では、Partial result cache: keys(part.P_PARTKEY) が PTRC のキャッシュノードです。

*************************** 1. row ***************************
EXPLAIN: -> Aggregate: sum(lineitem.L_EXTENDEDPRICE)
    -> Nested loop inner join  (cost=743267.04 rows=509876)
        -> Filter: ((part.P_CONTAINER = 'MED BOX') and (part.P_BRAND = 'Brand#34'))  (cost=204145.06 rows=19096)
            -> Table scan on part  (cost=204145.06 rows=1909557)
        -> Filter: (lineitem.L_QUANTITY < (select #2))  (cost=25.56 rows=27)
            -> Index lookup on lineitem using LINEITEM_FK2 (L_PARTKEY=part.P_PARTKEY)  (cost=25.56 rows=27)
            -> Select #2 (subquery in condition; dependent)
                -> Partial result cache: keys(part.P_PARTKEY)
                    -> Aggregate: avg(lineitem.L_QUANTITY)
                        -> Index lookup on lineitem using LINEITEM_FK2 (L_PARTKEY=part.P_PARTKEY)  (cost=28.23 rows=27)

前提条件

ご利用の PolarDB for MySQL クラスターは、バージョン 8.0、リビジョン 8.0.2.2.9 以降である必要があります。クラスターのバージョンは、「クエリエンジンバージョン」の手順に従って確認できます。

パラメーター

パラメーター

レベル

説明

partial_result_cache_enabled

グローバル/セッション

部分結果キャッシュ (PTRC) 機能を有効または無効にします。有効な値:

  • ON (デフォルト): PTRC 機能を有効にします。

  • OFF: PTRC 機能を無効にします。

partial_result_cache_cost_threshold

グローバル/セッション

PTRC のコストのしきい値です。オプティマイザーは、クエリの総コストがこのしきい値を超えた場合にのみ PTRC の使用を検討します。

有効値:0~18446744073709551615。デフォルト値:10000。

partial_result_cache_check_frequency

グローバル/セッション

動的フィードバックメカニズムがトリガーされる頻度です。キャッシュミスの累積回数がこの値に達すると、チェックが実行されます。

有効値:0~18446744073709551615。デフォルト値:200。

partial_result_cache_low_hit_rate

グローバル/セッション

キャッシュヒット率の下限ウォーターマークしきい値です。オプティマイザーは、推定ヒット率がこの値を上回る場合にのみ PTRC の使用を検討します。PTRC がすでに使用中の場合、実際のヒット率がこのしきい値を下回ると、動的フィードバックメカニズムによって無効化されます。

有効値:0~100。デフォルト値:20。

partial_result_cache_high_hit_rate

グローバル/セッション

キャッシュヒット率の上限ウォーターマークしきい値です。メモリ使用量が上限に達し、ヒット率がこの値を上回る場合、システムはキャッシュをメモリからディスクストレージに移動します。既存のキャッシュデータもディスクに移動されます。

有効値:0~100。デフォルト値:70。

partial_result_cache_max_mem_size

グローバル/セッション

単一のクエリに対して PTRC が使用できる累積メモリ量です。クエリに PTRC を使用する複数の演算子が含まれている場合、それらの合計メモリ使用量はこの制限を超えることはできません。

有効値:0~18446744073709551615。単位:バイト。デフォルト値:67108864。

コストベースの選択

PTRC の実行フローが示すように、PTRC を有効にすることが常に有益であるとは限りません。その有効性はキャッシュヒット率に依存します。ヒット率が低い場合、PTRC はキャッシュのチェックやメモリ使用量の増加などの操作によるパフォーマンスのオーバーヘッドを追加する可能性があります。

不要なオーバーヘッドを避けるため、オプティマイザーはコストベースのアプローチを使用して PTRC を使用するかどうかを決定します。主に次の 2 つの要素を評価します。

  • オプティマイザーは、クエリの総コストが partial_result_cache_cost_threshold の値を超える場合にのみ PTRC の使用を検討します。

  • 演算子の推定キャッシュヒット率は、partial_result_cache_low_hit_rate の値よりも高くなければなりません。

コストベースの決定を行う際、オプティマイザーはまず partial_result_cache_cost_threshold パラメーターをチェックします。

  • クエリの総コストがこのしきい値を下回る場合、オプティマイザーはそのクエリを低コストで、迅速に実行される可能性が高いと見なします。PTRC によるパフォーマンス向上は最小限であり、キャッシュチェックによるオーバーヘッドが、短時間で高同時実行数のクエリのレイテンシーを増加させる可能性があります。したがって、オプティマイザーはこのグローバルなコストのしきい値を使用して、低コストのクエリに対して PTRC を完全にバイパスします。これにより、オプティマイザーが PTRC の適格性を判断するためにすべての式を評価するオーバーヘッドも削減されます。

  • クエリの総コストが partial_result_cache_cost_threshold 以上の場合、オプティマイザーは PTRC の対象となるすべての演算子を評価し、次の数式を使用してキャッシュヒット率を推定します。

    hit_rate = (fanout - ndv) / fanout

    この数式では、fanout は演算子が実行されると予測される合計回数であり、ndv はすべての相関パラメーターの組み合わせである PTRC キーの個別値の数です。

推定 hit_ratepartial_result_cache_low_hit_rate の値より低い場合、オプティマイザーはその演算子に PTRC を使用しません。ただし、既存の MySQL コストモデルでは、統計はテーブルのインデックスまたはヒストグラムデータに依存します。相関パラメーターの列にインデックスやヒストグラムがない場合、オプティマイザーは `ndv` を正確に推定できません。このような場合、オプティマイザーは積極的に PTRC を有効にし、実行中の動的フィードバックメカニズムに依存して、その使用を継続するかどうかを判断することがあります。

動的フィードバックメカニズム

実行フェーズ中、すべてのキャッシュヒットまたはキャッシュミスが統計に記録されます。動的フィードバックメカニズムは、この情報を使用して実際のキャッシュヒット率を計算します。実際のキャッシュヒット率が partial_result_cache_low_hit_rate の値を下回った場合、メカニズムは実行の残り時間、PTRC を直ちに無効にします。これにより、クエリは元の実行計画に戻り、非効率なキャッシュによるオーバーヘッドが削減されます。

partial_result_cache_check_frequency パラメーターは、動的チェックが実行される頻度をコントロールします。これは、チェックをトリガーする累積キャッシュミス数を指定します。たとえば、デフォルト値が 200 の場合、動的フィードバックメカニズムは 200 回のキャッシュミス後にトリガーされます。

結果セットはメモリにキャッシュされるため、PTRC のメモリ使用量が上限に達した場合にも動的フィードバックメカニズムがトリガーされます。このシナリオでは、メカニズムはキャッシュヒット率が低すぎるかどうかをチェックするだけでなく、データエビクションを実行するか、結果セットをディスクに書き出すかも決定します。

PTRC のメモリ使用量が上限に達すると、次のフィードバックポリシーが適用されます。

  1. `hit_rate` が partial_result_cache_low_hit_rate の値を下回る場合、システムはヒット率が低すぎると判断し、PTRC を無効にします。

  2. `hit_rate` が partial_result_cache_high_hit_rate の値を上回る場合、システムはキャッシュデータをメモリからディスクストレージに移動します。ディスクベースのキャッシュでも、予測可能なパフォーマンス向上が期待できます。

  3. `hit_rate` が下限と上限のウォーターマークしきい値の間にある場合、システムは Least Recently Used (LRU) データエビクションポリシーをトリガーします。最も最近使用されていないデータがキャッシュからクリアされ、新しいデータのためのスペースが確保されます。新しいデータがキャッシュされた後に再度メモリ制限に達した場合、プロセスはステップ 1 から繰り返されます。

partial_result_cache_max_mem_size パラメーターは、単一クエリ内の PTRC の累積メモリ使用量を制限します。クエリ内のすべての PTRC インスタンスで使用される合計メモリがこの制限を超えると、システムはそれらすべてに対して動的フィードバックメカニズムをトリガーします。

パフォーマンスのテスト

コストベースの選択のセクションで説明したように、PTRC のパフォーマンス上の利点に影響を与える主な要因は次のとおりです。

  • 高速化される演算子の実行コストが十分に高いこと。演算子自体の実行コストが低い場合、キャッシュによる潜在的なパフォーマンス向上は限定的です。

  • キャッシュヒット率が高いこと。ヒット率が高いほど、より大きなパフォーマンス向上が得られます。

TPC-H Q17 テストを例に挙げます。

SELECT sum(l_extendedprice) / 7.0 AS avg_yearly
FROM lineitem, part
WHERE p_partkey = l_partkey
    AND p_brand = 'Brand#34'
    AND p_container = 'MED BOX'
    AND l_quantity < (
        SELECT 0.2 * avg(l_quantity)
        FROM lineitem
        WHERE l_partkey = p_partkey
    );

このクエリのサブクエリは何度も実行されます。次の実行計画は、PTRC が使用中であることを示しています。TPC-H Q17 の EXPLAIN ツリーでは、Partial result cache: keys(part.P_PARTKEY) ノードは、PTRC が依存サブクエリに適用されていることを示します。

EXPLAIN: -> Aggregate: sum(lineitem.L_EXTENDEDPRICE)
    -> Nested loop inner join  (cost=743267.04 rows=509876)
        -> Filter: ((part.P_CONTAINER = 'MED BOX') and (part.P_BRAND = 'Brand#34'))  (cost=204145.06 rows=19096)
            -> Table scan on part  (cost=204145.06 rows=1909557)
        -> Filter: (lineitem.L_QUANTITY < (select #2))  (cost=25.56 rows=27)
            -> Index lookup on lineitem using LINEITEM_FK2 (L_PARTKEY=part.P_PARTKEY)  (cost=25.56 rows=27)
            -> Select #2 (subquery in condition; dependent)
                -> Partial result cache: keys(part.P_PARTKEY)
                    -> Aggregate: avg(lineitem.L_QUANTITY)
                        -> Index lookup on lineitem using LINEITEM_FK2 (L_PARTKEY=part.P_PARTKEY)  (cost=28.23 rows=27)

テスト統計によると、TPC-H Q17 のサブクエリで PTRC を有効にすると、キャッシュヒット率が最大 96% に達し、大幅なパフォーマンス向上がもたらされます。次の図はテストデータを示しています。image

まとめ

PTRC は、単一クエリ内で相関パラメーターに依存する複雑な演算子を対象とします。これらの演算子の中間結果セットをキャッシュすることにより、冗長な計算を削減します。キャッシュヒット率が十分に高ければ、大幅なパフォーマンス向上を達成できます。現在、PTRC は、相関サブクエリやネステッドループ結合 (内部結合、外部結合、セミ結合、アンチ結合を含む) など、さまざまな演算子を高速化できます。