ClickHouse におけるテーブルのパーティションとは?
パーティションは、MergeTree エンジンファミリーのテーブルにあるデータパーツを、整理された論理的な単位としてまとめるための仕組みです。これは、時間範囲、カテゴリ、その他の主要な属性といった特定の基準に基づいて、概念的に意味のある形でデータを整理する方法です。こうした論理単位により、データの管理、クエリ、最適化がしやすくなります。
PARTITION BY
PARTITION BY toStartOfMonth(date) 句を追加して 拡張 します。これにより、テーブルのデータパーツが不動産売買の月ごとに整理されます。
ディスク上の構造
ClickHouse サーバーはまず、上の図に示されている 4 行の挿入例の行を、パーティションキーの値
toStartOfMonth(date) ごとに分割します。
次に、特定された各パーティションについて、通常どおり複数の連続した手順 (① ソート、② カラムへの分割、③ 圧縮、④ ディスクへの書き込み) で行が処理されます。
パーティション化を有効にすると、ClickHouse は各データパーツに対して自動的に MinMax indexes を作成する点に注意してください。これらは単に、パーティションキー式で使用される各テーブルカラムごとのファイルであり、そのデータパーツ内におけるそのカラムの最小値と最大値が含まれています。
パーティションごとのマージ
上の図のとおり、異なるパーティションに属するパーツがマージされることはありません。カーディナリティの高いパーティションキーを選ぶと、パーツが数千ものパーティションに分散し、マージ候補になることがないため、事前設定された制限を超えて、厄介な
Too many partsエラーの原因になります。この問題への対処は簡単です。適切なパーティションキーを選び、カーディナリティを 1000..10000 未満にしてください。
パーティションの監視
_partition_value を使うと、サンプルテーブルに存在する一意なパーティションの一覧をクエリできます。
あるいは、ClickHouse はすべてのテーブルのすべてのパーツとパーティションを system.parts システムテーブルで追跡しています。次のクエリは、上記のサンプルテーブルについて、すべてのパーティションの一覧に加え、パーティションごとの現在アクティブなパーツ数と、それらのパーツに含まれる行数の合計を返します。
テーブルのパーティションは何に使われますか?
データ管理
toStartOfMonth(date) でパーティション分割されているため、有効期限 (TTL) の条件を満たすパーティション全体 (テーブルパーツ の集合) が削除され、パーツを書き換えることなく クリーンアップ処理をより効率的に実行できます。
同様に、古いデータを削除する代わりに、よりコスト効率に優れた ストレージティア に自動的かつ効率的に移動することもできます:
クエリ最適化
date) と、テーブルの主キーに使われているカラム (town) の両方でフィルタリングすることで、2020 年 12 月にロンドンで売却されたすべての不動産の最高価格を算出します (date は主キーの一部ではありません) 。
ClickHouse はこのクエリを処理する際、無関係なデータを評価しないように、一連の pruning 手法を適用します。
① パーティションプルーニング: テーブルのパーティションキーに使われているカラムに対するクエリの filter に論理的に一致しないパーティション全体 (パーツの集合) を除外するために、MinMax indexes が使用されます。 ② Granule pruning: 手順 ① の後に残った data parts に対しては、プライマリインデックスを使い、テーブルの主キーに使われているカラムに対するクエリの filter に論理的に一致しないすべてのグラニュール (行の block) を除外します。 これらのデータ pruning のステップは、上記のクエリ例について、EXPLAIN 句を使って物理的なクエリ実行計画を確認することで観察できます。
date フィールドの MinMax index を使って、存在する 3257 個の グラニュール (行のブロック) のうち 11 個を特定し、それらが、クエリの date フィルターに一致する行を含む、436 個あるアクティブなデータパーツのうち 1 個に格納されていることを示しています。
② Granule pruning: 上記の EXPLAIN 出力の 19 行目から 24 行目は、続いて ClickHouse が、手順 ① で特定されたデータパーツの プライマリインデックス (town フィールドに対して作成されたもの) を使って、グラニュールの数 (クエリの town フィルターにも一致する可能性がある行を含むもの) を 11 から 1 にさらに絞り込むことを示しています。これは、さらに上で表示した、実行したクエリに対する ClickHouse-client の出力にも反映されています。
パーティション化は主にデータ管理のための機能です
uk_price_paid_simple_partitioned には 600 を超えるパーティションがあり、そのためアクティブなデータパーツは 600 306 個あります。一方、パーティション化されていないテーブル uk_price_paid_simple では、すべての初期データパーツがバックグラウンドマージによって 1 つのアクティブなパーツにまでマージされました。
上記のサンプルクエリをパーティションフィルターなしでパーティション化テーブルに対して実行したときの物理的なクエリ実行計画を、EXPLAIN 句で確認すると、以下の出力の 19 行目と 20 行目から、ClickHouse が既存のグラニュール (行のブロック) 3257 個のうち 671 個を、既存のアクティブなデータパーツ 436 個のうち 431 個にまたがって、クエリのフィルターに一致する行を含む可能性があるものとして特定していることがわかります。したがって、これらがクエリエンジンによってスキャンおよび処理されます: