クエリチューニングのレシピ
実用的なプレイブック:症状 → 根本原因 → 実証済みの修正。 プロファイルを開いて、注意すべき 指標を見つけたものの、「これからどうすればいい?」という疑問が残る場合に活用してください。
1 · 高速診断ワークフロー
-
実行概要をざっと見る
QueryPeakMemoryUsagePerNode > 80 %またはQuerySpillBytes > 1 GBの場合、メモリとディスクへのスピルのレシピに直接進みます。 -
最も遅い Pipeline / Operator を見つける
⟶ Query Profile UI で、OperatorTotalTime % でソートをクリックします。
最も負荷の高い operator は、次にどのレシピブロックを読むべきかを教えてくれます (Scan, Join, Aggregate, …)。 -
ボトルネックのサブタイプを確認する
各レシピは、その_シグネチャ_メトリックパターンから始まります。修正を試す前に、それらに一致させてください。
2 · Operator ごとのレシピ
2.1 OLAP / Connector Scan [metrics]
Scan Operator 内の様々なメトリクスをより良く理解するために、以下の図はこれらのメトリクスとストレージ構造の関連性を示しています。

ディスクからデータを取得し、述語を適用するために、ストレージエンジンはいくつかの手法を利用します。
- データストレージ: エンコードおよび圧縮されたデータは、セグメント内のディスクに格納され、様々なインデックスが付属しています。
- インデックスフィルタリング: エンジンは、BitmapIndex、BloomfilterIndex、ZonemapIndex、ShortKeyIndex、および NGramIndex などのインデックスを利用して、不要なデータをスキップします。
- Pushdown Predicates:
a > 1のような単純な述語は、特定の列で評価するためにプッシュダウンされます。 - 後期実体化: 必要な列とフィルタリングされた行のみがディスクから取得されます。
- Non-Pushdown Predicates: プッシュダウンできない述語が評価されます。
- Projection Expression:
SELECT a + 1などの式が計算されます。
Scan Operator は、IO タスクを実行するための追加のスレッドプールを利用します。したがって、このノードの時間メトリクス間の関係は、以下に示すとおりです。

一般的なパフォーマンスのボトルネック
コールドストレージまたは低速なストレージ – BytesRead、ScanTime、または IOTaskExecTime が支配的で、ディスク I/O が 80〜100 % 前後で推移している場合、スキャンはコールドストレージまたはプロビジョニング不足のストレージにアクセスしています。ホットデータを NVMe/SSD に移動し、Data Cache を有効にします。BE の datacache_* 設定(または従来の block_cache_*)でサイズを設定し、セッション enable_scan_datacache でスキャン時の使用を有効にします。
Filter のプッシュダウンの欠落 – PushdownPredicates が 0 付近にとどまり、ExprFilterRows が高い場合、述語はストレージ層に到達していません。それらを単純な比較として書き換えるか(%LIKE% や広範な OR チェーンを避ける)、zonemap/Bloom インデックスまたはマテリアライズドビューを追加して、プッシュダウンできるようにします。
スレッドプールの枯渇 – 高い IOTaskWaitTime と低い PeakIOTasks は、I/O の並行性が飽和してい ることを示しています。Data Cache を有効にしてサイズを設定し(BE datacache_* とセッション enable_scan_datacache)、ホットデータをより高速なストレージ(NVMe/SSD)に移動します。
tablet 間のデータスキュー – 最大値と最小値の OperatorTotalTime の間に大きな隔たりがある場合、一部の tablet は他の tablet よりもはるかに多くの作業を行っています。より高い基数のキーで再バケットするか、バケット数を増やして負荷を分散します。
Rowset/セグメントの断片化 – RowsetsReadCount/SegmentsReadCount の急増と長い SegmentInitTime は、多数の小さな rowset が存在することを示しています。手動 Compaction をトリガーし、小さなロードをバッチ処理して、セグメントを事前にマージします。
累積されたソフトデリート – 大きな DeleteFilterRows は、大量のソフトデリートの使用を示唆しています。BE Compaction を実行して、ソフトデリートをパージします。
2.2 集計 [metrics]
Aggregate Operator は、集計関数、GROUP BY、および DISTINCT の実行を担当します。
集計アルゴリズムの 複数の形式
| 形式 | プランナーが選択するタイミング | 内部データ構造 | ハイライト/注意点 |
|---|---|---|---|
| ハッシュ集計 | キーがメモリに収まる場合。カーディナリティが極端でない場合 | SIMDプロービングを備えたコンパクトなハッシュテーブル | デフォルトのパス。適度なキー数に最適です。 |
| ソートされた集計 | 入力が GROUP BY キーで既に順序付けられている場合 | 単純な行比較 + 実行状態 | ハッシュテーブルのコストがゼロ。プロービングの偏りが大きい場合に、多くの場合2〜3倍高速です。 |
| スピル可能な集計 (3.2+) | ハッシュテーブルがメモリ制限を超える場合 | ディスクスピルパーティションを使用したハイブリッドハッシュ/マージ | OOMを防ぎ、パイプラインの並行性を維持します。 |
マルチステージ分散集計
StarRocks では、集計は分散方式で実装されており、クエリパターンとオプティマイザの決定に応じてマルチステージになる場合があります。
┌─────────┐ ┌──────────┐ ┌────────────┐ ┌────────────┐