より高速なプルーニングと予測可能なデータレイアウトのための Fuse テーブルのパーティショニング
PARTITION BY は Fuse テーブルを物理的にパーティションへ分割します。TiDB Cloud Lake は異なるパーティション値のブロックとセグメントを分離して保持し、メタデータにパーティション値を記録し、クエリ述語に一致しないパーティションをプルーニングします。
大規模なテーブルが時間範囲、テナントまたはリージョン識別子、あるいは別の安定した次元で頻繁にフィルタリングされる場合は、パーティショニングを使用します。カーディナリティの高いキーには、BUCKET() を使用して固定数のハッシュパーティションを作成します。
どのような問題を解決するのか
パーティショニングとクラスタリングの比較
PARTITION BY と CLUSTER BY は互いに補完し合う機能です。
1 つのテーブルで両方を使用できます。パーティションキーは、ユーザーに見えるクラスターキーの一部にはなりません。
CREATE TABLE events (
event_time TIMESTAMP,
tenant_id BIGINT,
payload VARIANT
)
PARTITION BY (DATE_TRUNC(day, event_time))
CLUSTER BY (tenant_id, event_time);
クイックセットアップ
日単位でパーティショニングされたテーブルを作成します。
CREATE TABLE events (
event_id BIGINT,
event_time TIMESTAMP,
event_type STRING
)
PARTITION BY (DATE_TRUNC(day, event_time));
以降のすべての書き込みは、このパーティション境界に従います。
INSERT INTO events VALUES
(1, '2026-07-08 10:00:00', 'login'),
(2, '2026-07-08 18:30:00', 'purchase'),
(3, '2026-07-09 09:15:00', 'logout');
その後、時間に対する述語によって、無関係な日次パーティションをプルーニングできます。
EXPLAIN
SELECT *
FROM events
WHERE event_time >= TIMESTAMP '2026-07-08'
AND event_time < TIMESTAMP '2026-07-09';
EXPLAIN の出力では、partitions total と partitions scanned を比較し、range pruning の統計を確認してください。スキャンされたパーティション数が少ないほど、パーティションプルーニングが適用されていることを示します。
パーティショニング戦略
このセクションでは、TiDB Cloud Lake で Fuse テーブルをパーティショニングするさまざまな戦略について説明します。
時間ベースのパーティショニング
タイムスタンプまたは日付カラムに決定的な式を適用します。
-- Daily partitions
PARTITION BY (DATE_TRUNC(day, event_time))
-- Monthly partitions
PARTITION BY (DATE_TRUNC(month, event_time))
一般的なフィルタ条件に合った粒度を選びつつ、各パーティションが断片化を避けられるだけの十分な大きさになるようにしてください。日次パーティションは通常、データ量の多いイベントデータに適しています。月次パーティションは、データ量の少ない履歴データに適していることが多いです。
Identity パーティショニング
カラムが取りうる値の種類がすでに少なく、増減もほとんどない場合は、そのカラムを直接使用します。
CREATE TABLE regional_sales (
region STRING,
order_id BIGINT,
order_date DATE,
amount DECIMAL(18, 2)
)
PARTITION BY (region);
適した Identity キーには、リージョン、国、テナント階層、またはその他の上限がある業務上の次元が含まれます。一意 ID で直接パーティショニングするのは避けてください。
BUCKET() を使ったハッシュパーティショニング
BUCKET(<count>, <column>) は、サポートされる値を 0 から <count> - 1 の範囲の符号なしパーティション番号へ決定的にマッピングします。バケット数は、1 から 4294967295 までの定数整数である必要があります。
CREATE TABLE customer_events (
customer_id BIGINT,
event_time TIMESTAMP,
payload VARIANT
)
PARTITION BY (BUCKET(32, customer_id));
バケットパーティショニングは、等価フィルタがカーディナリティの高いカラムを対象とする一方で、値ごとに 1 つの物理パーティションを作成するのが現実的でない場合に有効です。
BUCKET() でサポートされる値のデータ型は、整数、文字列、日付、タイムスタンプです。詳細は BUCKET() を参照してください。
複合パーティショニング
複数の式を並べて、複合パーティションキーを構成します。
CREATE TABLE tenant_events (
tenant_id BIGINT,
event_time TIMESTAMP,
payload VARIANT
)
PARTITION BY (
DATE_TRUNC(month, event_time),
BUCKET(16, tenant_id)
);
各パーティション式は、テーブルのカラムを必ず 1 つだけ参照する必要があります。2 つのカラムでパーティショニングするには、上記のように個別の式を使用してください。tenant_id + another_id のような式は無効です。
ハッシュ分散書き込み
パーティションテーブルへの分散または高並列な取り込みでは、WRITE_DISTRIBUTION_MODE = 'hash' を設定します。
CREATE TABLE customer_events (
customer_id BIGINT,
event_time TIMESTAMP,
payload VARIANT
)
PARTITION BY (BUCKET(32, customer_id))
WRITE_DISTRIBUTION_MODE = 'hash';
このモードでは、評価済みのパーティションキーをハッシュ化し、同じパーティション値を持つ行をローカルソートの前に同じライターへルーティングします。複数のノードまたはパイプラインが同じパーティションへ同時に書き込む場合に、小さなブロックの断片化を減らせます。
WRITE_DISTRIBUTION_MODE には次の値を指定できます。
'none'(デフォルト): 書き込み前に行を再分散しません。'hash': 書き込み前にパーティションキーで行を再分散します。この値にはPARTITION BYが必要です。
ハッシュ再分散ではネットワークシャッフルが追加されます。ブロックレイアウトの改善効果がシャッフルコストを上回る、分散または並列のロードで有効にしてください。小規模な単一ライターの挿入では効果がない場合があります。
既存のテーブルへのパーティションキーの追加
ALTER TABLE ... PARTITION BY はテーブル定義のみを変更します。既存データは再分散されず、その後に OPTIMIZE TABLE や RECLUSTER を実行しても再分散されません。変更後に書き込まれたデータのみがパーティション化されます。
空のテーブル: キーを追加してからロードします。
ALTER TABLE events PARTITION BY (DATE_TRUNC(month, event_time));
INSERT INTO events SELECT * FROM source;
データがあるテーブル: キーを追加してからテーブルを書き直します。ORDER BY は維持してください。これがないと、書き直し時に非常に小さいブロックが書き込まれ、処理が遅くなります。
ALTER TABLE events PARTITION BY (DATE_TRUNC(month, event_time));
INSERT OVERWRITE events SELECT * FROM events ORDER BY DATE_TRUNC(month, event_time);
キーを変更する場合: いったんドロップし、新しいキーを追加してからテーブルを書き直します。
ALTER TABLE events DROP PARTITION KEY;
ALTER TABLE events PARTITION BY (DATE_TRUNC(day, event_time));
INSERT OVERWRITE events SELECT * FROM events ORDER BY DATE_TRUNC(day, event_time);
DROP PARTITION KEY はデータを書き直しません。パーティションプルーニングを停止し、WRITE_DISTRIBUTION_MODE を 'none' にリセットします。
行のパーティションキー値の更新
UPDATE と MERGE INTO は、行のパーティションキー値を変更できます。行は新しい値に対応するパーティションへ移動します。追加の操作は不要です。
-- Moves the row from the September partition to the October partition.
UPDATE events SET event_time = '2026-10-05 12:00:00' WHERE event_id = 42;
行の移動ではその行が書き直されるため、インプレース更新よりコストが高くなります。
式のルールとテーブル変更
Fuse テーブルのパーティション式については、次のルールがあります。
- 各式は決定的で、ちょうど 1 つのカラムを参照する必要があります。
- 複合パーティション化では、複数カラムの 1 つの式ではなく、複数の式を使用します。
BUCKET()では、1から4294967295までの定数のバケット数が必要です。- パーティションキーが参照するカラムは、ドロップしたりデータ型を変更したりできません。
- 参照されているカラムの名前を変更すると、保存されているパーティション式も更新されます。
- 内部の
partition_byメタデータはSET OPTIONSでは変更できません。 PARTITION BYは Fuse テーブルでサポートされています。その他のエンジンでは、異なるパーティション構文やセマンティクスが実装されている場合があります。