RANGE パーティショニングは、境界値を使用してテーブルやインデックスをセグメントに分割します。これは、時系列データや定期的なデータローテーションが必要な大規模テーブルに対する標準的なアプローチです。これにより、クエリオプティマイザーは無関係なセグメントを完全にスキップでき、行単位ではなくパーティションレベルでデータを追加または削除できます。
RANGE パーティショニングが適しているケース
パーティションプルーニングによる範囲クエリの高速化
大規模なテーブルが日付や数値範囲で頻繁にクエリされる場合——たとえば、注文テーブル(ORDER)や購入スケジュール(LINEITEM)など——は、範囲パーティション分割により、クエリ オプテマイザーが関係のないパーティションを完全にスキップできます。この手法は、パーティションプルーニングと呼ばれます。
例えば、`orders` テーブルを年単位でパーティション分割し、特定の 1 年間のデータをクエリする場合、オプティマイザーはすべてのパーティションをスキャンする代わりに、1 つのパーティションにのみアクセスします。8 年分のデータを持つテーブルに対して、1 年間を対象とするクエリは 8 つのパーティションのうち 1 つにしかアクセスしないため、I/O とスキャン時間がそれに比例して削減されます。
タンブリングウィンドウによるデータローテーションの簡素化
RANGE パーティショニングは、ローリングデータウィンドウ (例えば、直近 36 ヶ月分のデータを保持する) を維持するための標準的なアプローチです。新しい月の追加と最も古い月の削除は、行レベルではなくパーティションレベルで実行されます:
新しい月のデータをステージングテーブルにロードします。
ステージングテーブルをクリーンアップし、インデックスを作成します。
EXCHANGE PARTITIONを実行して、ステージングテーブルをパーティションテーブルと交換します。この間、パーティションテーブルはクエリ可能のままです。最も古い月のパーティションを削除するには、
DROP PARTITIONを実行します。
パーティション全体を操作することは、個々の行を削除したり、テーブル全体でインデックスを再構築したりするよりもはるかに効率的です。
管理性を高めるための大規模テーブルの分割
単一の大規模テーブルに対するバックアップおよびリストア操作は、メンテナンスウィンドウを超える可能性があります。RANGE パーティショニングはテーブルをより小さな論理ブロックに分割するため、個々のパーティションを独立してバックアップ、リストア、またはアーカイブできます。
RANGE パーティショニングの例
以下の例では、9年を超えるordersテーブルを示しています。このテーブルは、o_orderdate列によって8つの年次パーティション(オーバーフローパーティションを含む)にパーティション分割されています。このレイアウトは、パーティションプルーニングによる短間隔の販売分析と、ローリングウィンドウデータ管理の両方をサポートします。
CREATE TABLE `orders` (
`o_orderkey` int(11) NOT NULL,
`o_custkey` int(11) NOT NULL,
`o_orderstatus` char(1) DEFAULT NULL,
`o_totalprice` decimal(10,2) DEFAULT NULL,
`o_orderDATE` date NOT NULL,
`o_orderpriority` char(15) DEFAULT NULL,
`o_clerk` char(15) DEFAULT NULL,
`o_shippriority` int(11) DEFAULT NULL,
`o_comment` varchar(79) DEFAULT NULL,
PRIMARY KEY (`o_orderkey`,`o_orderDATE`,`o_custkey`),
KEY `o_orderkey` (`o_orderkey`),
KEY `i_o_custkey` (`o_custkey`),
KEY `i_o_orderdate` (`o_orderDATE`)
) ENGINE=InnoDB
PARTITION BY RANGE (TO_DAYS(o_orderdate))
(PARTITION item1 VALUES LESS THAN (TO_DAYS('1992-01-01')),
PARTITION item2 VALUES LESS THAN (TO_DAYS('1993-01-01')),
PARTITION item3 VALUES LESS THAN (TO_DAYS('1994-01-01')),
PARTITION item4 VALUES LESS THAN (TO_DAYS('1995-01-01')),
PARTITION item5 VALUES LESS THAN (TO_DAYS('1996-01-01')),
PARTITION item6 VALUES LESS THAN (TO_DAYS('1997-01-01')),
PARTITION item7 VALUES LESS THAN (TO_DAYS('1998-01-01')),
PARTITION item8 VALUES LESS THAN (TO_DAYS('1999-01-01')),
PARTITION item9 VALUES LESS THAN (MAXVALUE));パーティションプルーニングを確認するには、EXPLAIN を実行します。o_orderDATE = '1992-03-01' に対するクエリは、item2 のみにアクセスする必要があります:
EXPLAIN SELECT * FROM orders WHERE o_orderDATE = '1992-03-01';+----+-------------+--------+------------+------+---------------+---------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+---------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | orders | item2 | ref | i_o_orderdate | i_o_orderdate | 3 | const | 1 | 100.00 | NULL |
+----+-------------+--------+------------+------+---------------+---------------+---------+-------+------+----------+-------+RANGE 型の制限により、TO_DAYS()を使用してテーブルをパーティション分割し、SHOW CREATE TABLE文を実行した後、元の DDL 文が表示されない場合があります。パーティション境界は、日付文字列ではなく整数の日付値として表示されることがあります。これは既知の表示上の制限であり、クエリの動作には影響しません。
SHOW CREATE TABLE orders;CREATE TABLE `orders` (
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50100 PARTITION BY RANGE (to_days(`o_orderDATE`))
(PARTITION item1 VALUES LESS THAN (727563),
PARTITION item2 VALUES LESS THAN (727929),
PARTITION item3 VALUES LESS THAN (728294),
PARTITION item4 VALUES LESS THAN (728659),
PARTITION item5 VALUES LESS THAN (729024),
PARTITION item6 VALUES LESS THAN (729390),
PARTITION item7 VALUES LESS THAN (729755),
PARTITION item8 VALUES LESS THAN (730120),
PARTITION item9 VALUES LESS THAN MAXVALUE) */RANGE COLUMNS パーティショニング
RANGE COLUMNS パーティショニングは、以下の 3 つの点で RANGE パーティショニングを拡張したものです:
列名のみ:
RANGE COLUMNS()は、式ではなく列名を受け入れます。複数列サポート:
RANGE COLUMNS()は 1 つ以上の列を含むことができます。パーティションの配置は、スカラー値比較ではなくタプル比較によって決定されます。より広範な型をサポート: パーティションキー列には、INTEGER、STRING、DATE、または DATETIME 型を使用できます。
CREATE TABLE `orders` (
`o_orderkey` int(11) NOT NULL,
`o_custkey` int(11) NOT NULL,
`o_orderstatus` char(1) DEFAULT NULL,
`o_totalprice` decimal(10,2) DEFAULT NULL,
`o_orderDATE` date NOT NULL,
`o_orderpriority` char(15) DEFAULT NULL,
`o_clerk` char(15) DEFAULT NULL,
`o_shippriority` int(11) DEFAULT NULL,
`o_comment` varchar(79) DEFAULT NULL,
PRIMARY KEY (`o_orderkey`,`o_orderDATE`,`o_custkey`),
KEY `o_orderkey` (`o_orderkey`),
KEY `i_o_custkey` (`o_custkey`),
KEY `i_o_orderdate` (`o_orderDATE`)
) ENGINE=InnoDB
PARTITION BY RANGE COLUMNS(o_orderdate)
(PARTITION item1 VALUES LESS THAN ('1992-01-01'),
PARTITION item2 VALUES LESS THAN ('1993-01-01'),
PARTITION item3 VALUES LESS THAN ('1994-01-01'),
PARTITION item4 VALUES LESS THAN ('1995-01-01'),
PARTITION item5 VALUES LESS THAN ('1996-01-01'),
PARTITION item6 VALUES LESS THAN ('1997-01-01'),
PARTITION item7 VALUES LESS THAN ('1998-01-01'),
PARTITION item8 VALUES LESS THAN ('1999-01-01'),
PARTITION item9 VALUES LESS THAN (MAXVALUE));