🐷

TiDB Partition Pruning

に公開

過去3回にわたってTiDBのパーティション機能を触りながら見てきました。
https://zenn.dev/kameoncloud/articles/2dc11e5645f38c
https://zenn.dev/kameoncloud/articles/69e82ac560bb98
https://zenn.dev/kameoncloud/articles/8e764052ea5cfd

今日は最終回、Partition Pruning を見ていきます。

Partition Pruning とは

テーブルに格納されているデータが複数のパーティションに分割して保存されている場合、発行されたクエリが必要なパーティションのみを選択的にスキャンすることをいいます。
Pruningとは日本語で剪定という意味です。翻訳によっては整理とされるケースもあります。

さっそくやってみる

https://docs.pingcap.com/ja/tidb/stable/partitioned-table/#partition-pruning
ではこちらのドキュメントを読みつつ作業を進めていきます。
まずは範囲パーティション付きテーブルを作成します。

CREATE TABLE t1 (
    fname VARCHAR(50) NOT NULL,
    lname VARCHAR(50) NOT NULL,
    region_code TINYINT UNSIGNED NOT NULL,
    dob DATE NOT NULL
)

PARTITION BY RANGE( region_code ) (
    PARTITION p0 VALUES LESS THAN (64),
    PARTITION p1 VALUES LESS THAN (128),
    PARTITION p2 VALUES LESS THAN (192),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);

次に10件ほどダミーデータを挿入します。

INSERT INTO t1 (fname, lname, region_code, dob) VALUES
('Alice', 'Smith', 10, '1990-05-12'),
('Bob', 'Johnson', 50, '1985-08-23'),
('Charlie', 'Brown', 70, '1992-11-15'),
('David', 'Williams', 120, '1980-02-10'),
('Eve', 'Jones', 130, '1995-07-30'),
('Frank', 'Miller', 180, '1988-12-05'),
('Grace', 'Davis', 200, '1993-04-20'),
('Hank', 'White', 250, '1979-06-14'),
('Ivy', 'Clark', 90, '1991-09-25'),
('Jack', 'Hall', 160, '1983-03-08');

データをSQLで呼び出してみます。

SELECT fname, lname, region_code, dob
    FROM t1
    WHERE region_code > 128 AND region_code < 180;

WHERE region_code > 128 AND region_code < 180とありクエリ対象のデータは以下の定義に基づきパーティションp2にしか含まれないことがわかります。

    PARTITION p1 VALUES LESS THAN (128),
    PARTITION p2 VALUES LESS THAN (192),

EXPALINを付与したクエリ実行計画を見るとより明確にわかります。

EXPLAIN SELECT fname, lname, region_code, dob
    FROM t1
    WHERE region_code > 128 AND region_code < 180;

スキャン対象として明示的にp2のみが指定されています。

以下の様に複数のパーティションにまたがるSELECTを発行すると複数のパーティションをスキャンしていることがわかります。

EXPLAIN SELECT fname, lname, region_code, dob
    FROM t1
    WHERE region_code > 120 AND region_code < 180;


この場合p0,p3がスキャンされていませんので、p0p3がプルーニングされた、と表現します。

プルーニングが有効化される条件

プルーニングが正しく動作させるためには指定された条件は定数でなければならず、関数はここに指定できません。ただ例外として、UNIX_TIMESTAMP()、TO_DAYS()はパーティション作成時の条件として用いることは可能です。
以下の様にLIST側をとることも可能です。
パーティション列 IN (定数1、定数2、...、定数N)

EXPLAIN SELECT fname, lname, region_code, dob
    FROM t1
    WHERE region_code in (120,130);

またLIKE検索時にはプルーニングは動作しないようです。

その他細かい条件などはこちらをご覧ください。
https://docs.pingcap.com/ja/tidb/stable/partition-pruning/
https://docs.pingcap.com/ja/tidb/stable/partitioned-table/#partition-pruning

Discussion