メインコンテンツまでスキップ
メインコンテンツまでスキップ

低カーディナリティのパーティションキーを選択する

A data management technique

パーティショニングは主にデータ管理の手法であり、クエリ最適化ツールではありません。特定のワークロードでパフォーマンスを向上させることができますが、クエリを加速させるために最初に使用すべきメカニズムではありません。パーティショニングキーは慎重に選択する必要があり、その影響を明確に理解した上でデータのライフサイクルニーズやよく理解されたアクセスパターンに沿って適用されるべきです。

ClickHouseでは、パーティショニングは指定されたキーに基づいてデータを論理的なセグメントに整理します。これはテーブル作成時に PARTITION BY 句を使用して定義され、通常、行を時間間隔、カテゴリ、または他のビジネスに関連する次元でグループ化するために使用されます。パーティショニング式の各ユニークな値は、ディスク上の独自の物理パーティションを形成し、ClickHouseはこれらの値ごとにデータを別々のパーツで保存します。パーティショニングはデータ管理を改善し、保持ポリシーを簡素化し、特定のクエリパターンに役立つことがあります。

例えば、toStartOfMonth(date)というパーティショニングキーを持つ構造のUKの支払価格データセットテーブルを考えてみましょう。

CREATE TABLE uk.uk_price_paid_simple_partitioned
(
  date Date,
  town LowCardinality(String),
  street LowCardinality(String),
  price UInt32
)
ENGINE = MergeTree
ORDER BY (town, street)
PARTITION BY toStartOfMonth(date)

テーブルに行のセットが挿入されると、ClickHouseは挿入されたすべての行を含む単一のデータパートを作成するのではなく(こちらで説明されているように)、挿入された行の間で各ユニークなパーティションキー値ごとに1つの新しいデータパートを作成します。

Partitions

ClickHouseサーバーは、まず上記の図にスケッチされた4行の例の挿入から行をtoStartOfMonth(date)のパーティションキー値に従って分割します。次に、特定された各パーティションに対して、行は通常どおりにいくつかの逐次的な手順(① ソート、② カラムへの分割、③ 圧縮、④ ディスクへの書き込み)を実行することによって処理されます。

パーティショニングの詳しい説明については、このガイドをお勧めします。

パーティショニングが有効になっている場合、ClickHouseはパーティション間でなく、内部のデータパーツのみをマージします。これは以下のように上記の例のテーブルに対して示します:

Partitions

パーティショニングの適用

パーティショニングは、ClickHouseで大規模データセットを管理する強力なツールであり、とくに可観測性や分析のユースケースで効果的です。パーティション全体を削除、移動、またはアーカイブできるため、データライフサイクル操作を効率的に行えます。これは、多くの場合、行レベルの削除やコピー操作よりもはるかに高速でリソース集約型ではありません。また、パーティショニングはClickHouseのTTLや階層型ストレージなどの機能とシームレスに統合され、カスタムオーケストレーションなしで保持ポリシーやホット/コールドストレージ戦略を実装することが可能です。例えば、最近のデータは高速SSDストレージに保持され、古いパーティションは自動的に安価なオブジェクトストレージに移動されます。

パーティショニングはワークロードの一部でクエリパフォーマンスを改善する可能性がありますが、応答時間に悪影響を与える可能性もあります。

パーティショニングキーが主キーに含まれておらず、それでフィルタリングしている場合、ユーザーはパーティショニングを利用することでクエリパフォーマンスが向上するのを感じるかもしれません。例についてはこちらをご覧ください。

逆に、クエリがパーティションを横断する必要があると、全体のパーツ数が増加するため、パフォーマンスに悪影響を与える可能性があります。このため、ユーザーはパーティショニングをクエリ最適化技術として検討する前に、自分のアクセスパターンを理解する必要があります。

要約すると、ユーザーは主にパーティショニングをデータ管理手法と考えるべきです。データ管理の例については、可観測性ユースケースガイドの「"Managing Data"」やコアコンセプト - テーブルパーティションの「"What are table partitions used for?"」をご覧ください。

低いカーディナリティのパーティショニングキーを選択する

重要なことに、パーツの数が多いとクエリパフォーマンスに悪影響を与えます。そのため、ClickHouseは“too many parts”エラーで応答します。これは、合計またはパーティションごとに指定された制限を超える場合に発生します。

パーティショニングキーのカーディナリティを正しく選ぶことは重要です。高カーディナリティのパーティショニングキー - すなわち、異なるパーティション値の数が多い - はデータパーツの急増を招くことがあります。ClickHouseはパーティションを超えたパーツをマージしないため、パーティションが多すぎるとマージされていないパーツが多くなり、「Too many parts」エラーが最終的にトリガーされます。マージは必須であり、ストレージの断片化を減少させ、クエリスピードを最適化しますが、高カーディナリティのパーティションでは、そのマージの可能性が失われます。

対照的に、低カーディナリティのパーティショニングキー - すなわち、100 - 1,000個未満の異なる値 - が通常は最適です。これは効率的なパーツのマージを可能にし、メタデータのオーバーヘッドを低く保ち、ストレージにおける過剰なオブジェクト作成を避けます。また、ClickHouseはパーティションカラムにMinMaxインデックスを自動的に構築するため、これらのカラムでフィルタリングするクエリの速度を大幅に向上させることができます。たとえば、テーブルがtoStartOfMonth(date)でパーティション化されている場合、月ごとにフィルタリングすると、エンジンは関連のないパーティションとそのパーツを完全にスキップできます。

パーティショニングは、いくつかのクエリパターンでパフォーマンスを改善することがありますが、主にデータ管理機能です。すべてのパーティションを横断するクエリは、データの断片化の増加やスキャンされるパーツの数が増えるため、非パーティションテーブルを使用するよりも遅くなる可能性があります。パーティショニングは慎重に使用し、常に選択したキーが低カーディナリティであり、データライフサイクルポリシー(たとえば、TTLによる保持)に沿っていることを確認してください。パーティショニングが必要かどうか不明な場合は、まずパーティショニングなしで始め、観察されたアクセスパターンに基づいて後で最適化することをお勧めします。