19.2.2 LIST パーティショニング

MySQL の LIST パーティショニングは、多くの点で RANGE パーティショニングに似ています。RANGE によるパーティショニングと同様に、各パーティションを明示的に定義する必要があります。2 つのタイプのパーティショニングの主な違いは、LIST パーティショニングでは、各パーティションが、連続する値の範囲のセットのいずれかではなく、値リストのセットのいずれかに含まれるカラム値のメンバーシップに基づいて定義および選択されることです。これを行うには、PARTITION BY LIST (expr) を使用します。ここで、expr はカラム値またはカラム値に基づく式で、整数値を返し、VALUES IN (value_list) で各パーティションを定義します。ここで、value_list はカンマで区切られた整数のリストです。

注記

MySQL 5.6 では、LIST によってパーティション化するときに、整数 (および NULL も可。セクション19.2.7「MySQL パーティショニングによる NULL の扱い」を参照してください) のリストに対してのみ照合できます。

ただし、LIST COLUMN パーティショニングを使用するときは、ほかのカラムタイプを値リストで使用できます (これについては、このセクションで後述します)。

範囲で定義されるパーティションの場合と異なり、リストパーティションは特定の順序で宣言する必要はありません。構文についての詳細は、セクション13.1.17「CREATE TABLE 構文」を参照してください。

以降の例では、パーティション化するテーブルの基本定義が、次に示す CREATE TABLE ステートメントによって提供されることを想定します。

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
);

(これは、セクション19.2.1「RANGE パーティショニング」の例の出発点として使用したものと同じテーブルです。)

次の表に示すように、20 のビデオ店があり、それらが 4 つのフランチャイズに分類されていると想定します。

地域 店舗 ID 番号
3、5、6、9、17
1、2、10、11、19、20
西 4、12、13、14、18
中央 7、8、15、16

同じ地域に属する店舗の行が同じパーティションに格納されるようにこのテーブルをパーティション化するには、次のような CREATE TABLE ステートメントを使用できます。

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
)
PARTITION BY LIST(store_id) (
    PARTITION pNorth VALUES IN (3,5,6,9,17),
    PARTITION pEast VALUES IN (1,2,10,11,19,20),
    PARTITION pWest VALUES IN (4,12,13,14,18),
    PARTITION pCentral VALUES IN (7,8,15,16)
);

これにより、特定の地域に関連する従業員レコードをテーブルで簡単に追加または削除できるようになります。たとえば、西地域の全店舗が別の会社に売却されたとします。MySQL 5.6 では、その地域の店舗で働いていた従業員に関連するすべての行をクエリー ALTER TABLE employees TRUNCATE PARTITION pWest を使用して削除できます。これは、同等の DELETE ステートメント DELETE FROM employees WHERE store_id IN (4,12,13,14,18); よりもはるかに効率的に実行できます(ALTER TABLE employees DROP PARTITION pWest を使用してもこれらのすべての行が削除されますが、テーブルの定義からパーティション pWest も削除されるため、ALTER TABLE ... ADD PARTITION ステートメントを使用してテーブルの元のパーティショニングスキームをリストアする必要があります)。

RANGE パーティショニングと同様に、LIST パーティショニングとハッシュまたはキーによるパーティショニングを組み合わせることによって、複合パーティショニング (サブパーティショニング) を生成できます。セクション19.2.6「サブパーティショニング」を参照してください。

RANGE パーティショニングの場合と異なり、MAXVALUE などのすべての状況に対応するものはありません。パーティショニング式で予期されるすべての値を PARTITION ... VALUES IN (...) 句で指定してください。一致しないパーティショニングカラム値が含まれている INSERT ステートメントは、次の例に示すように、エラーで失敗します。

mysql> CREATE TABLE h2 (
    ->   c1 INT,
    ->   c2 INT
    -> )
    -> PARTITION BY LIST(c1) (
    ->   PARTITION p0 VALUES IN (1, 4, 7),
    ->   PARTITION p1 VALUES IN (2, 5, 8)
    -> );
Query OK, 0 rows affected (0.11 sec)

mysql> INSERT INTO h2 VALUES (3, 5);
ERROR 1525 (HY000): Table has no partition for value 3

単一 INSERT ステートメントを使用して複数の行を挿入するときの動作は、テーブルがトランザクションストレージエンジンを使用するかどうかによって変わります。InnoDB テーブルの場合、ステートメントは単一トランザクションと見なされ、一致しない値があるときはステートメントが完全に失敗し、行は挿入されません。MyISAM などの非トランザクションストレージエンジンを使用するテーブルの場合、一致しない値が含まれている行の前にある行は挿入されますが、あとにある行はされません。

このタイプのエラーは、IGNORE キーワードを使用することで無視させることができます。そうした場合、一致しないパーティショニングカラム値が含まれる行は挿入されませんが、一致する値を持つ行は挿入されてエラーが報告されません。

mysql> TRUNCATE h2;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM h2;
Empty set (0.00 sec)

mysql> INSERT IGNORE INTO h2 VALUES (2, 5), (6, 10), (7, 5), (3, 1), (1, 9);
Query OK, 3 rows affected (0.00 sec)
Records: 5  Duplicates: 2  Warnings: 0

mysql> SELECT * FROM h2;
+------+------+
| c1   | c2   |
+------+------+
|    7 |    5 |
|    1 |    9 |
|    2 |    5 |
+------+------+
3 rows in set (0.00 sec)

MySQL 5.6 は LIST COLUMNS パーティショニングのサポートを提供します。これは、LIST パーティショニングのバリアントで、パーティショニングカラムに整数型以外の型のカラムを使用したり、複数のカラムをパーティショニングキーとして使用したりできます。詳細は、セクション19.2.3.2「LIST COLUMNS パーティショニング」を参照してください。


User Comments
Sign Up Login You must be logged in to post a comment.