コンパクションの原理
1. コンパクションの役割
Apache Doris は LSM-Tree ベースのストレージエンジンを使用し、書き込み時には既存ファイルを直接更新せず、データを新しいデータファイルに順次追記します。 この設計によって高い書き込み性能を実現できますが、時間の経過とともにバージョンやサイズの異なるデータファイルが蓄積し、次の問題が生じます。
- クエリ性能の低下:複数のファイルに対する多方向マージソートが必要になる
- ストレージ領域の浪費:削除対象としてマークされたデータや重複データが残る
コンパクション(データの圧縮と整理)は、これらの問題を解決するための重要な仕組みです。バックグラウンドでデータファイルを自動的にマージして書き直し、同じ主キーまたは隣接する範囲のデータを、少数の整列されたファイルにまとめ、削除済みまたは期限切れのデータを除去します。 これにより、高いクエリ性能を維持しながらストレージ領域の使用効率を高めます。
Doris では、コンパクションは継続的かつ自動的に実行され、手動で起動する必要はありません。ただし、その原理と実行状態を理解することは、高い同時実行数や大量のデータを扱う場面での性能調整に役立ちます。
1.1 クエリ性能の向上
Doris のデータインポートでは、インポートごとに対象パーティション内の各タブレットに対して rowset が生成されます。
- 各 rowset には 0 個から n 個の segment が含まれる
- 各 segment はディスク上の整列されたファイルに対応する
クエリ時にストレージ層は集約または重複排除した結果を返す必要があるため、複数の rowset/segment のデータを多方向マージソートします。 rowset の数が増えるとマージ経路の数も増え、クエリ効率が低下します。
コンパクションの役割:
- BE ノードがバックグラウンドでこれらの rowset を継続的にマージし、マージ経路を減らしてクエリ効率を高める
- コンパクションはタブレット単位で実行される
1.2 データのクリーンアップ
コンパクションは性能向上に加え、データのクリーンアップも担います。
- 削除対象としてマークされたデータの除去
- Doris の DELETE 操作はデータをすぐには削除せず、削除用 rowset(実データではなく削除述語のみを含む)を生成します。コンパクション時に、この述語に一致するデータが除外され、実際に削除されます
- Merge-on-Write 型テーブルでは、削除マークが付いたデータもコンパクションの段階で除去されます
- 重複データの除去
- Aggregate モデル:同じキーを持つ行を集約する
- Unique モデル:同じキーに対して最新のデータのみを残す
これにより、データの正しさを確保するとともに、ストレージ領域の使用量を削減します。
2. 主要な概念
2.1 コンパクションスコア
コンパクションスコアは、タブレット内のデータの乱れ具合を測る指標であり、コンパクションの優先順位を決める基準にもなります。 これは、クエリ実行時にそのタブレットで必要となるマージ経路の数に相当します。
- スコアが高いほどクエリの処理負荷が高い
- そのため、コンパクションではスコアの高いタブレットを優先する
例:
"rowsets": [
"[0-100] 3 DATA NONOVERLAPPING 0200000000001c30804822f519cf378fbe6f162b7de393a6 500.32 MB",
"[101-101] 2 DATA OVERLAPPING 02000000000021d0804822f519cf378fbe6f162b7de393a6 180.46 MB",
"[102-102] 1 DATA NONOVERLAPPING 0200000000002211804822f519cf378fbe6f162b7de393a6 50.59 MB"
]
- [0-100] の rowset には 3 個の segment がありますが、重複がないため 1 経路を占めます
- [101-101] の rowset には重複する 2 個の segment があるため、2 経路を占めます
- [102-102] の rowset は 1 経路を占めます したがって、このタブレットのコンパクションスコアは 4 です。
2.2 コンパクションの種類
- Cumulative Compaction:小さな増分 rowset をマージして、マージ効率を高める
- Base Compaction:特定の rowset より前にあるすべての rowset を新しい rowset にマージする
- Full Compaction:すべての rowset をマージする
- Cumulative Point:Base Compaction と Cumulative Compaction を分ける境界点
理想的な戦略は、まず Cumulative Compaction で小さな rowset をマージし、一定の規模まで蓄積した後に Base Compaction を実行することです。
3. コンパクション戦略
3.1 タブレットの選択戦略
コンパクションの目的はクエリ性能を向上させることなので、コンパクションスコアが最も高いタブレットを優先します。
3.2 Rowset の選択戦略
対象のタブレットを決めたら、コンパクションに適した rowset を選択します。基本方針は次のとおりです。
- 計算負荷を抑えながら、コンパクションスコアをできるだけ下げる
- 書き込み増幅率を制御する
- システムリソースの過度な占有を避ける
主な考慮事項:
- 費用対効果
- Cumulative Compaction:マージ対象の rowset 間でサイズが大きく異ならないようにする。最大の rowset のサイズは合計の半分以下とする
- Base Compaction:Base rowset とほかの候補 rowset の比率が 0.3 以上の場合にのみ起動する
- 書き込み増幅の制御
- Cumulative Compaction:
- 候補 rowset のスコアが 5 を超える場合にのみ起動する
- データ量が promotion size を超える場合にのみ起動する
- Base Compaction:候補 rowset のスコアが 5 を超える場合にのみ起動する
- Cumulative Compaction:
- システムリソースの制御
- 単一の Cumulative Compaction に含める rowset 数は 1000 以下
- 単一の Base Compaction に含める rowset 数は 20 以下
4. コンパクションの処理

コンパクションの実行にはプロデューサー・コンシューマーモデルを使用します。
- タブレットのスキャンとタスク生成
- コンパクションタスクのプロデューサースレッドが定期的にすべてのタブレットをスキャンし、コンパクションスコアを計算する
- 各ラウンドで、各ディスクからスコアが最も高いタブレットを選択する
- 10 ラウンドごとに Base Compaction を選択し、残りの 9 ラウンドでは Cumulative Compaction を選択する
- 同時実行数の制御
- 現在のディスクで実行中のコンパクションタスク数が設定された上限を超えているか確認する
- 上限を超えていなければ、そのタブレットのコンパクションを許可する
- Rowset の選択
- サイズが近い連続した rowset を入力として選択する
- データ量の大きな差によって効率の悪い多方向マージが発生するのを避ける
- タスクの投入
- タブレットと候補 rowset をコンパクションタスクにまとめる
- タスクの種類(Base/Cumulative)に応じたスレッドプールのキューに投入する
- タスクの実行
- コンパクション用スレッドプールがキューからタスクを取得する
- 多方向マージソートを実行し、複数の rowset を新しい rowset にマージする
5. コンパクションの主なパラメータ
| パラメータ名 | 意味 | デフォルト値 |
|---|---|---|
| tive_compaction_rounds_for_each_base_compaction_round | Base Compaction のタスクを一つ生成するまでに生成する Cumulative Compaction のタスクのラウンド数。このパラメータを調整すると、Cumulative Compaction と Base Compaction のタスクの比率を制御できます | 9 |
| compaction_task_num_per_fast_disk | SSD ディスクあたりのコンパクションタスクの最大同時実行数 | 8 |
| compaction_task_num_per_disk | HDD ディスクあたりのコンパクションタスクの最大同時実行数 | 4 |
| max_base_compaction_threads | Base Compaction のスレッドプール内のワーカースレッド数 | 4 |
| max_cumu_compaction_threads | Cumulative Compaction のスレッドプール内のワーカースレッド数。-1 の場合、スレッドプールのサイズはディスク数によって決まり、ディスクごとにスレッドが一つ割り当てられます | -1 |
| base_compaction_min_rowset_num | Base Compaction の起動条件。rowset 数に基づいて起動する場合、Base Compaction に必要な rowset の最小数です | 5 |
| base_compaction_max_compaction_score | Base Compaction に参加する rowset のコンパクションスコアの最大値 | 20 |
| cumulative_compaction_min_deltas | Cumulative Compaction に参加する rowset のコンパクションスコアの最小値 | 5 |
| cumulative_compaction_max_deltas | Cumulative Compaction に参加する rowset のコンパクションスコアの最大値 | 1000 |