Skip to main content
ほとんどの場合、パーティションキーは必要ありません。また、日単位でのパーティション化が一般的なオブザーバビリティのユースケースを除き、月単位より細かいパーティションキーも通常は不要です。細かすぎるパーティション化は決して使用しないでください。クライアント識別子や名前でデータをパーティション化してはいけません。代わりに、クライアント識別子または名前を ORDER BY 式の最初のカラムにしてください。
パーティション化は、MergeTree family tables (レプリケートテーブルmaterialized view を含む) で利用できます。 パーティションは、指定した条件に基づいてテーブル内のレコードを論理的にまとめたものです。月ごと、日ごと、イベントタイプごとなど、任意の条件でパーティションを設定できます。各パーティションは個別に保存されるため、このデータの操作が容易になります。データにアクセスする際、ClickHouse は可能な限り最小のパーティション集合を使用します。パーティションキーを含むクエリでは、ClickHouse がパーティション内のパーツやグラニュールを選択する前に、そのパーティションで絞り込みを行うため、パーティション化はパフォーマンス向上に役立ちます。 パーティションは、テーブル作成時PARTITION BY expr 句で指定します。パーティションキーには、テーブルのカラムを使った任意の式を指定できます。たとえば、月単位のパーティション化を指定するには、toYYYYMM(date_column) 式を使用します。
パーティションキーには、式のタプルを使用することもできます (主キー と同様) 。例:
この例では、現在の週に発生したイベントタイプごとにパーティション化を設定します。 デフォルトでは、浮動小数点のパーティションキーはサポートされていません。これを使用するには、設定 allow_floating_point_partition_key を有効にします。 テーブルに新しいデータを挿入すると、そのデータは主キーでソートされた個別のパーツ (chunk) として保存されます。挿入後 10〜15 分で、同じパーティション内のパーツは 1 つの完全なパーツにマージされます。
マージは、パーティション化式の値が同じデータパーツに対してのみ実行されます。つまり、パーティションを細かくしすぎるべきではありません (目安は約 1,000 パーティション以下です) 。そうしないと、ファイルシステム内のファイル数や開かれたファイルディスクリプタが過剰になり、SELECT クエリのパフォーマンスが低下します。
テーブルのパーツとパーティションを確認するには、system.parts テーブルを使用します。たとえば、月ごとにパーティション化された visits テーブルがあるとします。system.parts テーブルに対して SELECT クエリを実行してみましょう。
partition カラムにはパーティション名が入ります。この例には 2 つのパーティションがあり、201901201902 です。ALTER … PARTITION クエリでは、このカラムの値を使ってパーティション名を指定できます。 name カラムには、パーティションのデータパーツ名が入ります。ALTER ATTACH PART クエリでは、このカラムを使ってパーツ名を指定できます。 パーツ名 201901_1_9_2_11 を分解してみましょう。
  • 201901 はパーティション名です。
  • 1 はデータブロックの最小番号です。
  • 9 はデータブロックの最大番号です。
  • 2 は chunk レベルです (このパーツの元になったマージツリーの深さ) 。
  • 11 は mutation バージョンです (パーツが mutation された場合) 。
旧形式のテーブルのパーツ名は 20190117_20190123_2_2_0 です (最小日付 - 最大日付 - 最小ブロック番号 - 最大ブロック番号 - レベル) 。
active カラムはパーツの状態を示します。1 はアクティブ、0 は非アクティブです。非アクティブなパーツには、たとえば、より大きなパーツにマージされたあとに残る元のパーツがあります。破損したデータパーツも非アクティブとして示されます。 例を見ると、同じパーティションに複数の独立したパーツがあることがわかります (たとえば 201901_1_3_1201901_1_9_2) 。これは、これらのパーツがまだマージされていないことを意味します。ClickHouse は、挿入されたデータのパーツを定期的にマージします。通常、マージは挿入から約 15 分後に実行されます。また、OPTIMIZE クエリを使って、スケジュール外のマージを実行することもできます。例:
非アクティブなパーツは、マージから約10分後に削除されます。 パーツやパーティションの一覧を確認する別の方法は、テーブルのディレクトリ /var/lib/clickhouse/data/<database>/<table>/ に入ることです。例えば:
‘201901_1_1_0’、‘201901_1_7_1’ などのフォルダは、パーツのディレクトリです。各パーツは対応するパーティションに属しており、特定の月のデータだけを含みます (この例のテーブルは月単位でパーティション化されています) 。 detached ディレクトリには、DETACH クエリを使ってテーブルからデタッチされたパーツが格納されます。破損したパーツも削除される代わりに、このディレクトリに移動されます。サーバーは detached ディレクトリ内のパーツを使用しません。ATTACH クエリを実行するまでは、このディレクトリ内のデータはいつでも追加、削除、変更できますが、サーバーはそれを認識しません。 稼働中のサーバーでは、ファイルシステム上でパーツの集合やそのデータを手動で変更することはできない点に注意してください。サーバーがその変更を認識しないためです。非レプリケートテーブルでは、サーバー停止中であればこれを行えますが、推奨されません。レプリケートテーブルでは、いかなる場合でもパーツの集合は変更できません。 ClickHouse では、パーティションに対して削除、あるテーブルから別のテーブルへのコピー、バックアップの作成といった操作を実行できます。すべての操作の一覧については、Manipulations With Partitions and Parts セクションを参照してください。

パーティションキーを使った Group By の最適化

テーブルのパーティションキーとクエリの Group By キーの組み合わせによっては、各パーティションごとに独立して集計を実行できる場合があります。 その場合、最後にすべての実行スレッドから部分的に集計されたデータをマージする必要はありません。 これは、各 Group By キーの値が 2 つの異なるスレッドのワーキングセットにまたがって現れないことが保証されるためです。 典型的な例は次のとおりです。
このようなクエリのパフォーマンスは、テーブルのレイアウトに依存します。この最適化はバージョン 26.7 以降ではデフォルトで有効になっており、パーティションのレイアウトが不利な場合には、ランタイムヒューリスティクスによって自動的にスキップされます。具体的には、パーティション数が少なすぎる場合 (max_threads / 2 未満)、パーティション数が多すぎる場合 (max_number_of_partitions_for_independent_aggregation より多い場合)、またはパーティションサイズの偏りが大きい場合 (最大のパーティションの行数が、総行数を max_threads で割った値の 2 倍を超える場合) です。以下の一覧では、一般に良好なパフォーマンスのためのレイアウト要因を説明しています。このうち、ランタイムヒューリスティクスで実際に適用されるのは、パーティション数とサイズの偏りだけです。
良好なパフォーマンスを得るための主な要因は次のとおりです。
  • クエリに含まれるパーティション数が十分に多いこと (max_threads / 2 より大きいこと) 。そうでないと、クエリはマシンを十分に活用できません
  • パーティションが小さすぎないこと。そうしないと、バッチ処理が行単位の処理に近くなってしまいます
  • パーティションのサイズが同程度であること。そうすることで、すべてのスレッドがほぼ同じ量の処理を行えます
データを各パーティションに均等に分散するために、PARTITION BY 句のカラムに何らかのハッシュ関数を適用することを推奨します。
関連する設定は次のとおりです。
  • allow_aggregate_partitions_independently - この最適化の使用を有効にするかどうかを制御します
  • force_aggregate_partitions_independently - 正しさの観点では適用可能であるものの、その有効性を見積もる内部ロジックによって無効化される場合でも、使用を強制します
  • max_number_of_partitions_for_independent_aggregation - テーブルが持てるパーティションの最大数に対するハードリミット
最終更新日 2026年7月23日