ClickHouse のテーブルのパーツとは何ですか?
ClickHouse の MergeTree engine family に含まれる各テーブルのデータは、ディスク上では不変の データパーツ の集合として構成されています。
これを説明するために、イギリスで売買された不動産の取引日、町、通り、価格を記録した この テーブル (UK property prices dataset をもとに調整) を使用します:
CREATE TABLE uk.uk_price_paid_simple
(
date Date,
town LowCardinality(String),
street LowCardinality(String),
price UInt32
)
ENGINE = MergeTree
ORDER BY (town, street);このテーブルは、ClickHouse SQL Playground でクエリを実行できます。
テーブルに一連の行が挿入されるたびに、データパーツが作成されます。以下の図はその概要を示したものです。

ClickHouse server が上の図に示した 4 行のサンプル insert (たとえば INSERT INTO ステートメント 経由) を処理すると、いくつかのステップが実行されます。
ソート
行はテーブルのソートキー (town, street) に従ってソートされ、ソート後の行に対して スパースプライマリインデックス が生成されます。
分割
ソート済みのデータはカラムごとに分割されます。
圧縮
各カラムは圧縮されます。
ディスクへの書き込み
圧縮されたカラムは、insert のデータパーツを表す新しいディレクトリ内に、バイナリのカラムファイルとして保存されます。スパースプライマリインデックスも圧縮され、同じディレクトリに格納されます。
テーブルで使用しているエンジンによっては、ソートとあわせて追加の変換が行われる場合があります。
データパーツは自己完結型であり、中央カタログがなくても内容を解釈するために必要なすべてのメタデータを含んでいます。スパースプライマリインデックスに加え、パーツには、セカンダリのデータスキッピングインデックス、カラム STATISTICS、チェックサム、min-max 索引 (パーティション化 を使用している場合) など、さらに多くのメタデータが含まれます。
パーツのマージ
テーブルごとのパーツ数を管理するため、バックグラウンドマージジョブが定期的に小さなパーツをより大きなパーツへ統合し、設定可能な圧縮サイズ (通常は約 150 GB) に達するまでこの処理を続けます。マージ済みパーツは非アクティブとしてマークされ、設定可能な期間の経過後に削除されます。時間の経過とともに、このプロセスによってマージ済みパーツの階層構造が形成されるため、これが MergeTree テーブルと呼ばれる理由です。

初期パーツ数とマージのオーバーヘッドを最小限に抑えるため、データベースクライアントでは、たとえば一度に 20,000 行を挿入するようにタプルをまとめて挿入するか、非同期挿入モードを使用することが推奨されています。このモードでは、ClickHouse は同じテーブルに対する複数の受信 INSERT の行をバッファリングし、バッファサイズが設定可能なしきい値を超えるか、タイムアウトになるまで、新しいパーツを作成しません。
テーブルのパーツの監視
仮想カラム _part を使用すると、サンプルテーブルで現在存在するすべてのアクティブなパーツの一覧をクエリできます。
SELECT _part
FROM uk.uk_price_paid_simple
GROUP BY _part
ORDER BY _part ASC; ┌─_part───────┐
1. │ all_0_5_1 │
2. │ all_12_17_1 │
3. │ all_18_23_1 │
4. │ all_6_11_1 │
└─────────────┘上記のクエリは、ディスク上のディレクトリ名を取得します。各ディレクトリは、テーブルのアクティブなデータパーツを表しています。これらのディレクトリ名の各部分にはそれぞれ特定の意味があり、さらに詳しく知りたい方のためにこちらで説明されています。
別の方法として、ClickHouse はすべてのテーブルのすべてのパーツに関する情報を system.parts システムテーブルで追跡しており、次のクエリは、上記の例のテーブルについて、現在アクティブなすべてのパーツ、そのマージレベル、およびそれらのパーツに格納されている行数の一覧を返します。
SELECT
name,
level,
rows
FROM system.parts
WHERE (database = 'uk') AND (`table` = 'uk_price_paid_simple') AND active
ORDER BY name ASC; ┌─name────────┬─level─┬────rows─┐
1. │ all_0_5_1 │ 1 │ 6368414 │
2. │ all_12_17_1 │ 1 │ 6442494 │
3. │ all_18_23_1 │ 1 │ 5977762 │
4. │ all_6_11_1 │ 1 │ 6459763 │
└─────────────┴───────┴─────────┘マージレベルは、そのパーツが追加でマージされるたびに1ずつ増加します。レベルが0であれば、これはまだマージされていない新しいパーツであることを示します。