Query Cache
Query Cache は、StarRocks の強力な機能で、集計クエリのパフォーマンスを大幅に向上させることができます。ローカル集計の中間結果をメモリに保存することで、以前と同じまたは類似の新しいクエリに対して不要なディスクアクセスや計算を回避できます。Query Cache を使用することで、StarRocks は集計クエリに 対して迅速かつ正確な結果を提供し、時間とリソースを節約し、より良いスケーラビリティを実現します。Query Cache は、多くのユーザーが大規模で複雑なデータセットに対して類似のクエリを実行する hc シナリオで特に有用です。
この機能は v2.5 からサポートされています。
v2.5 では、Query Cache は単一のフラットテーブルに対する集計クエリのみをサポートしています。v3.0 以降、Query Cache はスタースキーマで結合された複数のテーブルに対する集計クエリもサポートします。
適用シナリオ
次のシナリオで Query Cache を使用することをお勧めします。
- 個々のフラットテーブルやスタースキーマで結合された複数のテーブルに対して頻繁に集計クエリを実行する。
- 集計クエリのほとんどが非 GROUP BY 集計クエリであり、低カーディナリティの GROUP BY 集計クエリである。
- データが時間パーティションで追加モードでロードされ、アクセス頻度に基づいてホットデータとコールドデータに分類できる。
Query Cache は、次の条件を満たすクエリをサポートします。
-
クエリエンジンが Pipeline である。Pipeline エンジンを有効にするには、セッション変数
enable_pipeline_engine
をtrue
に設定します。NOTE
他のクエリエンジンは Query Cache をサポートしていません。
-
クエリがネイティブ OLAP テーブル(v2.5 以降)またはク ラウドネイティブテーブル(v3.0 以降)に対するものである。Query Cache は外部テーブルに対するクエリをサポートしていません。Query Cache は、計画が同期マテリアライズドビューへのアクセスを必要とするクエリもサポートします。ただし、非同期マテリアライズドビューへのアクセスを必要とするクエリはサポートしていません。
-
クエリが個々のテーブルまたは複数の結合されたテーブルに対する集計クエリである。
NOTE
- Query Cache は Broadcast Join と Bucket Shuffle Join をサポートしています。
- Query Cache は、Join 演算子を含む 2 つのツリー構造をサポートしています: Aggregation-Join と Join-Aggregation。Aggregation-Join ツリー構造では Shuffle Join はサポートされておらず、Join-Aggregation ツリー構造では Hash Join はサポートされていません。
-
クエリに
rand
、random
、uuid
、sleep
などの非決定的関数が含まれていない。
Query Cache は、次のパーティションポリシーを使用するテーブルに対するクエリをサポートします: 非パーティション、マルチカラムパーティション、シングルカラムパーティション。
機能の境界
- Query Cache は、Pipeline エンジンの per-tablet 計算に基づいています。per-tablet 計算とは、パイプラインドライバーがタブレット全体を一つずつ処理できることを意味し、タブレットの一部や多くのタブレットを交互に処理す ることはありません。クエリごとに各 BE が処理する必要のあるタブレットの数が、このクエリを実行するために呼び出されるパイプラインドライバーの数以上である場合、Query Cache は機能します。呼び出されるパイプラインドライバーの数は、実際の並行度(DOP)を表します。タブレットの数がパイプラインドライバーの数より少ない場合、各パイプラインドライバーは特定のタブレットの一部のみを処理します。この状況では、per-tablet 計算結果を生成できないため、Query Cache は機能しません。
- StarRocks では、集計クエリは少なくとも 4 つのステージで構成されます。最初のステージで AggregateNode によって生成された per-tablet 計算結果は、OlapScanNode と AggregateNode が同じフラグメントからデータを計算する場合にのみキャッシュされます。他のステージで AggregateNode によって生成された per-tablet 計算結果はキャッシュされません。一部の DISTINCT 集計クエリでは、セッション変数
cbo_cte_reuse
がtrue
に設定されている場合、データを生成する OlapScanNode と、生成されたデータを消費するステージ 1 の AggregateNode が異なるフラグメントからデータを計算し、ExchangeNode によってブリッジされている場合、Query Cache は機能しません。以下の 2 つの例は、CTE 最適化が実行され、Query Cache が機能しないシナリオを示しています:- 出力列が集計関数
avg(distinct)
を使用して計算される。 - 出力列が複数の DISTINCT 集計関数を使用して計算される。
- 出力列が集計関数
- データが集計前にシャッフルされる場合、そのデータに対するクエリを Query Cache は加速できません。
- テーブルの group-by 列または重複排除列が高カーディナリティの列である場合、そのテーブルに対する集計クエリで大きな結果が生成されます。このような場合、クエリは実行時に Query Cache をバイパスします。
- Query Cache は、計算結果を保存するために BE によって提供される少量のメモリを占有します。Query Cache のサイズはデフォルトで 512 MB です。したがって、Query Cache が大きなサイズのデータ項目を保存するのには適していません。さらに、Query Cache を有効にした後、キャッシュヒット率が低い場合、クエリパフォーマンスが低下します。したがって、タブレットに対して生成された計算結果のサイズが
query_cache_entry_max_bytes
またはquery_cache_entry_max_rows
パラメータで指定されたしきい値を超える場合、Query Cache はそのクエリに対して機能しなくなり、クエリは Passthrough モードに切り替わります。
動作の仕組み
Query Cache が有効になっている場合、各 BE はクエリのローカル集計を次の 2 つのステージに分割します。
-
Per-tablet 集計
BE は各タブレットを個別に処理します。BE がタブレットの処理を開始するとき、まず Query Cache を調べて、そのタブレットの集計の中間結果が Query Cache にあるかどうかを確認します。もしそうであれば(キャッシュヒット)、BE は Query Cache から直接中間結果を取得します。もしそうでなければ(キャッシュミス)、BE はディスク上のデータにアクセスし、ローカル集計を実行し て中間結果を計算します。BE がタブレットの処理を終了すると、そのタブレットの集計の中間結果を Query Cache に格納します。
-
Inter-tablet 集計
BE はクエリに関与するすべてのタブレットから中間結果を収集し、それらを最終結果に統合します。
将来的に類似のクエリが発行されると、以前のクエリのキャッシュされた結果を再利用できます。例えば、次の図に示すクエリは 3 つのタブレット(タブレット 0 から 2)を含み、最初のタブレット(タブレット 0)の中間結果はすでに Query Cache にあります。この例では、BE はディスク上のデータにアクセスする代わりに、Query Cache から直接タブレット 0 の結果を取得できます。Query Cache が完全にウォームアップされている場合、すべてのタブレットの中間結果を含むことができ、したがって BE はディスク上のデータにアクセスする必要がありません。
余分なメモリを解放するために、Query Cache は LRU(Least Recently Used)ベースのエビクションポリシーを採用して、キャッシュエントリを管理します。このエビクションポリシーに従って、Query Cache が占有するメモリの量が事前に定義されたサイズ(query_cache_capacity
)を超えると、最も最近使用されていないキャッシュエントリが Query Cache から削除されます。
NOTE
将来的に、StarRocks はキャッシュエントリを Query Cache から削除できる TTL(Time to Live)ベースのエビクションポリシーもサポートします。
FE は、各クエリが Query Cache を使用して加速する必要があるかどうかを判断し、クエリを正規化して、クエリの意味に影響を与えない些細なリテラルの詳細を排除します。
Query Cache の悪いケースによって引き起こされるパフォーマンスの低下を防ぐために、BE は実行時に Query Cache をバイパスする適応ポリシーを採用しています。
Query Cache の有効化
このセクションでは、Query Cache を有効にして構成するために使用されるパラメータとセッション変数について説明します。
FE セッション変数
変数 | デフォルト値 | 動的に構成可能か | 説明 |
---|---|---|---|
enable_query_cache | false | Yes | Query Cache を有効にするかどうかを指定します。有効な値: true と false 。true はこの機能を有効にし、false はこの機能を無効にします。Query Cache が有効になっている場合、このトピックの「適用シナリオ」セクションで指定された条件を満たすクエリに対してのみ機能します。 |
query_cache_entry_max_bytes | 4194304 | Yes | Passthrough モードをトリガーするしきい値を指定します。有効な値: 0 から 9223372036854775807 。クエリによってアクセスされる特定のタブレットの計算結果のバイト数または行数が query_cache_entry_max_bytes または query_cache_entry_max_rows パラメータで指定されたしきい値を超える場合、クエリは Passthrough モードに切り替わります。query_cache_entry_max_bytes または query_cache_entry_max_rows パラメータが 0 に設定されている場合、関与するタブレットから計算結果が生成されていない場合でも Passthrough モードが使用されます。 |
query_cache_entry_max_rows | 409600 | Yes | 上記と同じ。 |
BE パラメータ
BE 構成ファイル be.conf で次のパラメータを構成する必要があります。このパラメータを BE に対して再構成した後、BE を再起動して新しいパラメータ設定を有効にする必要があります。
パラメータ | 必須 | 説明 |
---|---|---|
query_cache_capacity | No | Query Cache のサイズを指定します。単位: バイト。デフォルトのサイズは 512 MB です。 各 BE はメモリ内に独自のローカル Query Cache を持ち、独自の Query Cache のみを格納および調べます 。 Query Cache のサイズは 4 MB 未満にすることはできません。BE のメモリ容量が期待する Query Cache サイズをプロビジョニングするのに不十分な場合、BE のメモリ容量を増やすことができます。 |
すべてのシナリオでの最大キャッシュヒット率を実現するための設計
クエリが文字通り同一でない場合でも Query Cache が有効な 3 つのシナリオを考慮します。これらの 3 つのシナリオは次のとおりです。
- 意味的に同等のクエリ
- スキャンされたパーティションが重複するクエリ
- 追加のみのデータ変更があるデータに対するクエリ(UPDATE または DELETE 操作なし)
意味的に同等のクエリ
2 つのクエリが類似している場合、それは文字通り同一である必要はありませんが、実行計画において意味的に同等のスニペットを含んでいることを意味します。それらは意味的に同等と見なされ、互いの計算結果を再利用できます。広義には、2 つのクエリが同じソースからデータをクエリし、同じ計算方法を使用し、同じ実行計画を持っている場合、それらは意味的に同等です。StarRocks は、2 つのクエリが意味的に同等であるかどうかを評価するために次のルールを適用します。
-
2 つのクエリに複数の集計が含まれている場合、それらの最初の集計が意味的に同等である限り、それらは意味的に同等と評価されます。例えば、次の 2 つのクエリ Q1 と Q2 は、どちらも複数の集計を含んでいますが、最初の集計が意味的に同等です。したがって、Q1 と Q2 は意味的に同等と評価されます。
-
Q1
SELECT
(
ifnull(sum(murmur_hash3_32(hour)), 0) + ifnull(sum(murmur_hash3_32(k0)), 0) + ifnull(sum(murmur_hash3_32(__c_0)), 0)
) AS fingerprint
FROM
(
SELECT
date_trunc('hour', ts) AS hour,
k0,
sum(v1) AS __c_0
FROM
t0
WHERE
ts between '2022-01-03 00:00:00'
and '2022-01-03 23:59:59'
GROUP BY
date_trunc('hour', ts),
k0
) AS t; -
Q2
SELECT
date_trunc('hour', ts) AS hour,
k0,
sum(v1) AS __c_0
FROM
t0
WHERE
ts between '2022-01-03 00:00:00'
and '2022-01-03 23:59:59'
GROUP BY
date_trunc('hour', ts),
k0
-
-
2 つのクエリが次のいずれかのクエリタイプに属している場合、それらは意味的に同等と評価される可能性があります。HAVING 句を含むクエリは、HAVING 句を含まないクエリと意味的に同等と評価されることはありません。ただし、ORDER BY または LIMIT 句の有無は、2 つのクエリが意味的に同等であるかどうかの評価に影響を与えません。
-
GROUP BY 集計
SELECT <GroupByItems>, <AggFunctionItems>
FROM <Table>
WHERE <Predicates> [and <PartitionColumnRangePredicate>]
GROUP BY <GroupByItems>
[HAVING <HavingPredicate>]NOTE
上記の例では、HAVING 句はオプションです。
-
GROUP BY DISTINCT 集計
SELECT DISTINCT <GroupByItems>, <Items>
FROM <Table>
WHERE <Predicates> [and <PartitionColumnRangePredicate>]
GROUP BY <GroupByItems>
HAVING <HavingPredicate>
-
NOTE
上記の例では、HAVING 句はオプションです。
-
非 GROUP BY 集計
SELECT <AggFunctionItems> FROM <Table>
WHERE <Predicates> [and <PartitionColumnRangePredicate>] -
非 GROUP BY DISTINCT 集計
SELECT DISTINCT <Items> FROM <Table>
WHERE <Predicates> [and <PartitionColumnRangePredicate>] -
どちらかのクエリに
PartitionColumnRangePredicate
が含まれている場合、2 つのクエリが意味的に同等かどうかを評価する前にPartitionColumnRangePredicate
が削除されます。PartitionColumnRangePredicate
は、次のタイプのいずれかの述語を指定し、パーティション列を参照します。col between v1 and v2
: パーティション列の値が [v1, v2] 範囲内にあることを示します。ここで、v1
とv2
は定数式です。v1 < col and col < v2
: パーティション列の値が (v1, v2) 範囲内にあることを示します。ここで、v1
とv2
は定数式です。v1 < col and col <= v2
: パーティション列の値が (v1, v2] 範囲内にあることを示します。ここで、v1
とv2
は定数式です。v1 <= col and col < v2
: パーティション列の値が [v1, v2) 範囲内にあることを示します。ここで、v1
とv2
は定数式です。v1 <= col and col <= v2
: パーティション列の値が [v1, v2] 範囲内にあることを示します。ここで、v1
とv2
は定数式です。
-
2 つのクエリの SELECT 句の出力列が再配置された後に同じである場合、2 つのクエリは意味的に同等と評価されます。
-
2 つのクエリの GROUP BY 句の出力列が再配置され た後に同じである場合、2 つのクエリは意味的に同等と評価されます。
-
2 つのクエリの WHERE 句の残りの述語が
PartitionColumnRangePredicate
を削除した後に意味的に同等である場合、2 つのクエリは意味的に同等と評価されます。 -
2 つのクエリの HAVING 句の述語が意味的に同等である場合、2 つのクエリは意味的に同等と評価されます。
次の lineorder_flat
テーブルを例として使用します。
CREATE TABLE `lineorder_flat`
(
`lo_orderdate` date NOT NULL COMMENT "",
`lo_orderkey` int(11) NOT NULL COMMENT "",
`lo_linenumber` tinyint(4) NOT NULL COMMENT "",
`lo_custkey` int(11) NOT NULL COMMENT "",
`lo_partkey` int(11) NOT NULL COMMENT "",
`lo_suppkey` int(11) NOT NULL COMMENT "",
`lo_orderpriority` varchar(100) NOT NULL COMMENT "",
`lo_shippriority` tinyint(4) NOT NULL COMMENT "",
`lo_quantity` tinyint(4) NOT NULL COMMENT "",
`lo_extendedprice` int(11) NOT NULL COMMENT "",
`lo_ordtotalprice` int(11) NOT NULL COMMENT "",
`lo_discount` tinyint(4) NOT NULL COMMENT "",
`lo_revenue` int(11) NOT NULL COMMENT "",
`lo_supplycost` int(11) NOT NULL COMMENT "",
`lo_tax` tinyint(4) NOT NULL COMMENT "",
`lo_commitdate` date NOT NULL COMMENT "",
`lo_shipmode` varchar(100) NOT NULL COMMENT "",
`c_name` varchar(100) NOT NULL COMMENT "",
`c_address` varchar(100) NOT NULL COMMENT "",
`c_city` varchar(100) NOT NULL COMMENT "",
`c_nation` varchar(100) NOT NULL COMMENT "",
`c_region` varchar(100) NOT NULL COMMENT "",
`c_phone` varchar(100) NOT NULL COMMENT "",
`c_mktsegment` varchar(100) NOT NULL COMMENT "",
`s_name` varchar(100) NOT NULL COMMENT "",
`s_address` varchar(100) NOT NULL COMMENT "",
`s_city` varchar(100) NOT NULL COMMENT "",
`s_nation` varchar(100) NOT NULL COMMENT "",
`s_region` varchar(100) NOT NULL COMMENT "",
`s_phone` varchar(100) NOT NULL COMMENT "",
`p_name` varchar(100) NOT NULL COMMENT "",
`p_mfgr` varchar(100) NOT NULL COMMENT "",
`p_category` varchar(100) NOT NULL COMMENT "",
`p_brand` varchar(100) NOT NULL COMMENT "",
`p_color` varchar(100) NOT NULL COMMENT "",
`p_type` varchar(100) NOT NULL COMMENT "",
`p_size` tinyint(4) NOT NULL COMMENT "",
`p_container` varchar(100) NOT NULL COMMENT ""
)
ENGINE=OLAP
DUPLICATE KEY(`lo_orderdate`, `lo_orderkey`)
COMMENT "olap"
PARTITION BY RANGE(`lo_orderdate`)
(PARTITION p1 VALUES [('0000-01-01'), ('1993-01-01')),
PARTITION p2 VALUES [('1993-01-01'), ('1994-01-01')),
PARTITION p3 VALUES [('1994-01-01'), ('1995-01-01')),
PARTITION p4 VALUES [('1995-01-01'), ('1996-01-01')),
PARTITION p5 VALUES [('1996-01-01'), ('1997-01-01')),
PARTITION p6 VALUES [('1997-01-01'), ('1998-01-01')),
PARTITION p7 VALUES [('1998-01-01'), ('1999-01-01')))
DISTRIBUTED BY HASH(`lo_orderkey`)
PROPERTIES
(
"replication_num" = "3",
"colocate_with" = "groupxx1",
"storage_format" = "DEFAULT",
"enable_persistent_index" = "false",
"compression" = "LZ4"
);
次の 2 つのクエリ Q1 と Q2 は、lineorder_flat
テーブルに対して意味的に同等です。以下の処理を行った後に同等と評価されます。
- SELECT 文の出力列を再配置します。
- GROUP BY 句の出力列を再配置します。
- ORDER BY 句の出力列を削除します。
- WHERE 句の述語を再配置します。
PartitionColumnRangePredicate
を追加します。
-
Q1
SELECT sum(lo_revenue), year(lo_orderdate) AS year,p_brand
FROM lineorder_flat
WHERE p_category = 'MFGR#12' AND s_region = 'AMERICA'
GROUP BY year,p_brand
ORDER BY year,p_brand; -
Q2
SELECT year(lo_orderdate) AS year, p_brand, sum(lo_revenue)
FROM lineorder_flat
WHERE s_region = 'AMERICA' AND p_category = 'MFGR#12' AND
lo_orderdate >= '1993-01-01' AND lo_orderdate <= '1993-12-31'
GROUP BY p_brand, year(lo_orderdate)
意味的同等性はクエリの物理計画に基づいて評価されます。 したがって、クエリのリテラルの違いは意味的同等性の評価に影響を与えません。さらに、定数式はクエリから削除され、クエリの最適化中に cast
式も削除されます。したがって、これらの式は意味的同等性の評価に影響を与えません。第三に、列とリレーションのエイリアスも意味的同等性の評価に影響を与えません。
スキャンされたパーティションが重複するクエリ
Query Cache は述語ベースのクエリ分割をサポートします。
述語の意味に基づいてクエリを分割することで、部分的な計算結果の再利用を実現します。クエリにテーブルのパーティション列を参照する述語が含まれ、その述語が値の範囲を指定する場合、StarRocks はテーブルのパーティションに基づいて範囲を複数の区間に分割できます。各個別の区間からの計算結果は、他のクエリによって個別に再利用できます。
次の t0
テーブルを例として使用します。
CREATE TABLE if not exists t0
(
ts DATETIME NOT NULL,
k0 VARCHAR(10) NOT NULL,
k1 BIGINT NOT NULL,
v1 DECIMAL64(7, 2) NOT NULL
)
ENGINE=OLAP
DUPLICATE KEY(`ts`, `k0`, `k1`)
COMMENT "OLAP"
PARTITION BY RANGE(ts)
(
START ("2022-01-01 00:00:00") END ("2022-02-01 00:00:00") EVERY (INTERVAL 1 day)
)
DISTRIBUTED BY HASH(`ts`, `k0`, `k1`)
PROPERTIES
(
"replication_num" = "3",
"storage_format" = "default"
);
テーブル t0
は日ごとにパーティション化されており、列 ts
はテーブルのパーティション列です。次の 4 つのクエリのうち、Q2、Q3、Q4 は Q1 のキャッシュ された計算結果の一部を再利用できます。
-
Q1
SELECT date_trunc('day', ts) as day, sum(v0)
FROM t0
WHERE ts BETWEEN '2022-01-02 12:30:00' AND '2022-01-14 23:59:59'
GROUP BY day;Q1 の述語
ts between '2022-01-02 12:30:00' and '2022-01-14 23:59:59'
によって指定された値の範囲は、次の区間に分割できます。1. [2022-01-02 12:30:00, 2022-01-03 00:00:00),
2. [2022-01-03 00:00:00, 2022-01-04 00:00:00),
3. [2022-01-04 00:00:00, 2022-01-05 00:00:00),
...
12. [2022-01-13 00:00:00, 2022-01-14 00:00:00),
13. [2022-01-14 00:00:00, 2022-01-15 00:00:00), -
Q2
SELECT date_trunc('day', ts) as day, sum(v0)
FROM t0
WHERE ts >= '2022-01-02 12:30:00' AND ts < '2022-01-05 00:00:00'
GROUP BY day;Q2 は Q1 の次の区間内の計算結果を再利用できます。
1. [2022-01-02 12:30:00, 2022-01-03 00:00:00),
2. [2022-01-03 00:00:00, 2022-01-04 00:00:00),
3. [2022-01-04 00:00:00, 2022-01-05 00:00:00), -
Q3
SELECT date_trunc('day', ts) as day, sum(v0)
FROM t0
WHERE ts >= '2022-01-01 12:30:00' AND ts <= '2022-01-10 12:00:00'
GROUP BY day;Q3 は Q1 の次の区間内の計算結果を再利用できます。
2. [2022-01-03 00:00:00, 2022-01-04 00:00:00),
3. [2022-01-04 00:00:00, 2022-01-05 00:00:00),
...
8. [2022-01-09 00:00:00, 2022-01-10 00:00:00), -
Q4
SELECT date_trunc('day', ts) as day, sum(v0)
FROM t0
WHERE ts BETWEEN '2022-01-02 12:30:00' and '2022-01-02 23:59:59'
GROUP BY day;Q4 は Q1 の次の区間内の計算結果を再利用できます。
1. [2022-01-02 12:30:00, 2022-01-03 00:00:00),
部分的な計算結果の再利用のサポートは、使用されるパーティションポリシーによって異なります。次の表に示すように、サポートの状況が異なります。
パーティションポリシー | 部分的な計算結果の再利用のサポート |
---|---|
非パーティション | サポートされていません |
マルチカラムパーティション | サポートされていません NOTE この機能は将来的にサポートされる可能性があります。 |
シングルカラムパーティション | サポートされています |
追加のみのデータ変更があるデータに対するクエリ
Query Cache はマルチバージョンキャッシングをサポートします。
データロードが行われると、タブレットの新しいバージョンが生成されます。その結果、タ ブレットの以前のバージョンから生成されたキャッシュされた計算結果は古くなり、最新のタブレットバージョンに遅れをとります。この状況では、マルチバージョンキャッシングメカニズムは、Query Cache に保存された古い結果とディスクに保存されたタブレットの増分バージョンをマージして、タブレットの最終結果を生成し、新しいクエリが最新のタブレットバージョンを持つことができるようにします。マルチバージョンキャッシングは、テーブルタイプ、クエリタイプ、およびデータ更新タイプによって制約されます。
マルチバージョンキャッシングのサポートは、テーブルタイプとクエリタイプによって異なります。次の表に示すように、サポートの状況が異なります。
テーブルタイプ | クエリタイプ | マルチバージョンキャッシングのサポート |
---|---|---|
重複キーテーブル |
|
|
集計テーブル | ベーステーブルに対するクエリまたは同期マテリアライズドビューに対するクエリ | 次の状況を除き、すべての状況でサポートされています: ベーステーブルのスキーマに 集計関数 replace が含まれている。クエリの GROUP BY、HAVING、または WHERE 句が集計列を参照する。増分タブレットバージョンにデータ削除レコードが含まれている。 |
ユニークキーテーブル | 該当なし | サポートされていません。ただし、Query Cache はサポートされています。 |
主キーテーブル | 該当なし | サポートされていません。ただし、Query Cache はサポートされています。 |
データ更新タイプがマルチバージョンキャッシングに与える影響は次のとおりです。
-
データ削除
増分バージョンのタブレットに削除操作が含まれている場合、マルチバージョンキャッシングは機能しません。
-
データ挿入
-
タブレットに対して空のバージョンが生成された場合、Query Cache にあるタブレットの既存データは有効であり、引き続き取得可能です。
- タブレットに対して非空のバージョンが生成された場合、Query Cache にあるタブレットの既存データは有効ですが、そのバージョンはタブレットの最新バージョンに遅れをとります。この状況では、StarRocks は既存データのバージョンからタブレットの最新バージョンまでの増分データを読み取り、既存データと増分データをマージし、マージされたデータを Query Cache に格納します。
-
スキーマ変更とタブレットの切り捨て
テーブルのスキーマが変更されたり、特定のタブレットが切り捨てられたりすると、テーブルに新しいタブレットが生成されます。その結果、Query Cache にあるテーブルのタブレットの既存データは無効になります。
メトリクス
Query Cache が機能するクエリのプロファイルには、CacheOperator
統計が含まれています。
クエリのソースプランにおいて、パイプラインに OlapScanOperator
が含まれている場合、OlapScanOperator
と集計演算子の名前は ML_
でプレフィックスされ、パイプラインが MultilaneOperator
を使用して per-tablet 計算を実行することを示します。CacheOperator
は ML_CONJUGATE_AGGREGATE
の前に挿入され、Query Cache が Passthrough、Populate、および Probe モードでどのように実行されるかを制御するロジックを処理します。クエリのプロファイルには、Query Cache の使用状況を理解するのに役立つ次の CacheOperator
メトリクスが含まれています。
メトリクス | 説明 |
---|---|
CachePassthroughBytes | Passthrough モードで生成されたバイト数。 |
CachePassthroughChunkNum | Passthrough モードで生成されたチャンク数。 |
CachePassthroughRowNum | Passthrough モードで生成された行数。 |
CachePassthroughTabletNum | Passthrough モードで生成されたタブレット数。 |
CachePassthroughTime: | Passthrough モードでの計算時間。 |
CachePopulateBytes | Populate モードで生成されたバイト数。 |
CachePopulateChunkNum | Populate モードで生成されたチャンク数。 |
CachePopulateRowNum | Populate モードで生成された行数。 |
CachePopulateTabletNum | Populate モードで生成されたタブレット数。 |
CachePopulateTime | Populate モードでの計算時間。 |
CacheProbeBytes | Probe モードでのキャッシュヒットに対して生成されたバイト数。 |
CacheProbeChunkNum | Probe モードでのキャッシュヒットに対して生成されたチャンク数。 |
CacheProbeRowNum | Probe モードでのキャッシュヒットに対して生成された行数。 |
CacheProbeTabletNum | Probe モードでのキャッシュヒットに対して生成されたタブレット数。 |
CacheProbeTime | Probe モードでの計算時間。 |
CachePopulate
XXX
メトリクスは、Query Cache が更新されるキャッシュミスに関する統計を提供します。
CachePassthrough
XXX
メトリクスは、生成された per-tablet 計算結果のサイズが大きいために Query Cache が更新されないキャッシュミスに関する統計を提供します。
CacheProbe
XXX
メトリクスは、キャッシュヒットに関する統計を提供します。
マルチバージョンキャッシングメカニズムでは、CachePopulate
メトリクスと CacheProbe
メトリクスには同じタブレット統計が含まれる場合があり、CachePassthrough
メトリクスと CacheProbe
メトリクスにも同じタブレット統計が含まれる場合があります。例えば、StarRocks が各タブレットのデータを計算する際、タブレットの履歴バージョンで生成された計算結果にヒットします。この状況では、StarRocks は履歴バージョンからタブレットの最新バージョン までの増分データを読み取り、データを計算し、増分データとキャッシュされたデータをマージします。マージ後に生成された計算結果のサイズが query_cache_entry_max_bytes
または query_cache_entry_max_rows
パラメータで指定されたしきい値を超えない場合、タブレットの統計は CachePopulate
メトリクスに収集されます。それ以外の場合、タブレットの統計は CachePassthrough
メトリクスに収集されます。
RESTful API 操作
-
metrics |grep query_cache
この API 操作は、Query Cache に関連するメトリクスをクエリするために使用されます。
curl -s http://<be_host>:<be_http_port>/metrics |grep query_cache
# TYPE starrocks_be_query_cache_capacity gauge
starrocks_be_query_cache_capacity 536870912
# TYPE starrocks_be_query_cache_hit_count gauge
starrocks_be_query_cache_hit_count 5084393
# TYPE starrocks_be_query_cache_hit_ratio gauge
starrocks_be_query_cache_hit_ratio 0.984098
# TYPE starrocks_be_query_cache_lookup_count gauge
starrocks_be_query_cache_lookup_count 5166553
# TYPE starrocks_be_query_cache_usage gauge
starrocks_be_query_cache_usage 0
# TYPE starrocks_be_query_cache_usage_ratio gauge
starrocks_be_query_cache_usage_ratio 0.000000 -
api/query_cache/stat
この API 操作は、Query Cache の使用状況をクエリするために使用されます。
curl http://<be_host>:<be_http_port>/api/query_cache/stat
{
"capacity": 536870912,
"usage": 0,
"usage_ratio": 0.0,
"lookup_count": 5025124,
"hit_count": 4943720,
"hit_ratio": 0.983800598751394
} -
api/query_cache/invalidate_all
この API 操作は、Query Cache をクリアするために使用されます。
curl -XPUT http://<be_host>:<be_http_port>/api/query_cache/invalidate_all
{
"status": "OK"
}
上記の API 操作のパラメータは次のとおりです。
be_host
: BE が存在するノードの IP アドレス。be_http_port
: BE が存在するノードの HTTP ポート番号。
注意事項
- StarRocks は、初めて開始されたクエリの計算結果を Query Cache に格納する必要があります。その結果、クエリパフォーマンスが期待よりもわずかに低下し、クエリのレイテンシが増加します。
- 大きな Query Cache サイズを構成すると、BE でクエリ評価にプロビジョニングできるメモリの量が減少します。Query Cache サイズがクエリ評価にプロビジョニングされたメモリ容量の 1/6 を超えないことをお勧めします。
- 処理する必要のあるタブレットの数が
pipeline_dop
の値より少ない場合、Query Cache は機能しません。Query Cache を機能させるには、pipeline_dop
を1
などの小さい値に設定できます。v3.0 以降、StarRocks はクエリの並行性に基づいてこのパラメータを適応的に調整します。