サブパーティショニング (複合パーティショニングとも呼ばれます) は、パーティション化されたテーブルの各パーティションをさらに分割することです。次の CREATE TABLE
ステートメントを検討します。
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) )
SUBPARTITIONS 2 (
PARTITION p0 VALUES LESS THAN (1990),
PARTITION p1 VALUES LESS THAN (2000),
PARTITION p2 VALUES LESS THAN MAXVALUE
);
テーブル ts
には 3 つの RANGE
パーティションがあります。これらの各パーティション (p0
、p1
、および p2
) は、さらに 2 つのサブパーティションに分割されます。実際には、テーブル全体が 3 * 2 = 6
パーティションに分割されます。ただし、PARTITION BY RANGE
句のアクションによって、これらの最初の 2 つには purchased
カラムで値が 1990 より小さいレコードのみが格納されます。
MySQL 5.6 では、RANGE
または LIST
によってパーティション化されたテーブルをサブパーティション化できます。サブパーティショニングには、HASH
または KEY
パーティショニングを使用できます。これは、複合パーティショニングとも呼ばれます。
SUBPARTITION BY HASH
および SUBPARTITION BY KEY
は通常それぞれ、PARTITION BY HASH
および PARTITION BY KEY
と同じ構文規則に従います。これの例外は、SUBPARTITION BY KEY
は現在 (PARTITION BY KEY
と異なり) デフォルトカラムをサポートしないことで、この目的に使用されるカラムを指定する必要があります (テーブルに明示的な主キーがある場合でも)。これは既知の問題であり、対処中です。詳細および例については サブパーティションに関する問題を参照してください。
SUBPARTITION
句を使用して個々のサブパーティションのオプションを指定することによって、サブパーティションを明示的に定義することもできます。たとえば、前の例と同じテーブル ts
をより冗長な形式で作成するには、次のようにします。
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0,
SUBPARTITION s1
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s2,
SUBPARTITION s3
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4,
SUBPARTITION s5
)
);
構文に関するいくつかの注意事項を次に示します。
各パーティションには、同じ数のサブパーティションが必要です。
-
パーティション化されたテーブルのパーティションに
SUBPARTITION
を使用してサブパーティションを明示的に定義する場合は、それらのすべてを定義する必要があります。言い換えると、次のステートメントは失敗します。CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( PARTITION p0 VALUES LESS THAN (1990) ( SUBPARTITION s0, SUBPARTITION s1 ), PARTITION p1 VALUES LESS THAN (2000), PARTITION p2 VALUES LESS THAN MAXVALUE ( SUBPARTITION s2, SUBPARTITION s3 ) );
このステートメントは、
SUBPARTITIONS 2
句を含んでいた場合でも失敗します。 各
SUBPARTITION
句には、(少なくとも) サブパーティションの名前が含まれている必要があります。それ以外は、サブパーティションに適切なオプションを設定するか、またはそのオプションのデフォルト設定を想定します。-
サブパーティション名はテーブル全体で一意である必要があります。たとえば、次の
CREATE TABLE
ステートメントは MySQL 5.6 で有効です。CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( PARTITION p0 VALUES LESS THAN (1990) ( SUBPARTITION s0, SUBPARTITION s1 ), PARTITION p1 VALUES LESS THAN (2000) ( SUBPARTITION s2, SUBPARTITION s3 ), PARTITION p2 VALUES LESS THAN MAXVALUE ( SUBPARTITION s4, SUBPARTITION s5 ) );
サブパーティションは、非常に大きいテーブルで、データおよびインデックスを多数のディスクに分散するために使用できます。/disk0
、/disk1
、/disk2
などとしてマウントされた 6 個のディスクがあるとします。ここで次の例を検討します。
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0
DATA DIRECTORY = '/disk0/data'
INDEX DIRECTORY = '/disk0/idx',
SUBPARTITION s1
DATA DIRECTORY = '/disk1/data'
INDEX DIRECTORY = '/disk1/idx'
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s2
DATA DIRECTORY = '/disk2/data'
INDEX DIRECTORY = '/disk2/idx',
SUBPARTITION s3
DATA DIRECTORY = '/disk3/data'
INDEX DIRECTORY = '/disk3/idx'
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
SUBPARTITION s5
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
)
);
この場合、各 RANGE
のデータおよびインデックスに個別のディスクが使用されます。ほかにも多数のバリエーションが考えられます。別の例を次に示します。
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE(YEAR(purchased))
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0a
DATA DIRECTORY = '/disk0'
INDEX DIRECTORY = '/disk1',
SUBPARTITION s0b
DATA DIRECTORY = '/disk2'
INDEX DIRECTORY = '/disk3'
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s1a
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
SUBPARTITION s1b
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s2a,
SUBPARTITION s2b
)
);
この場合は、次のように格納されます。
-
purchased
日付が 1990 年より前の行には大きな領域が使用されるため、4 つに分割され、パーティションp0
を構成する 2 つの各サブパーティション (s0a
およびs0b
) のデータおよびインデックスに個別のディスクが専用に割り当てられます。言い換えると、次のようになります。サブパーティション
s0a
のデータは/disk0
に格納されます。サブパーティション
s0a
のインデックスは、/disk1
に格納されます。サブパーティション
s0b
のデータは、/disk2
に格納されます。サブパーティション
s0b
のインデックスは、/disk3
に格納されます。
-
1990 年から 1999 年までの日付 (パーティション
p1
) が含まれている行は、1990 年より前の行ほどの領域を必要としません。これらは、p0
に格納されるレガシーレコードの場合の 4 つのディスクではなく、2 つのディスク (/disk4
および/disk5
) に分割されます。p1
の最初のサブパーティション (s1a
) に属するデータおよびインデックスは、/disk4
(データは/disk4/data
、およびインデックスは/disk4/idx
) に格納されます。p1
の 2 番目のサブパーティション (s1b
) に属するデータおよびインデックスは、/disk5
(データは/disk5/data
、およびインデックスは/disk5/idx
) に格納されます。
-
2000 年から現在までの日付 (パーティション
p2
) を反映する行には、前の 2 つの範囲で必要とされたほどの領域は使用されません。現在のところ、これらのすべてをデフォルトの場所に格納しても問題ありません。将来、2000 年から始まる 10 年間の購入数が、デフォルトの場所では十分な領域を提供できないほど増えたときには、
ALTER TABLE ... REORGANIZE PARTITION
ステートメントを使用して対応する行を移動できます。これを行う方法については、セクション19.3「パーティション管理」を参照してください。
NO_DIR_IN_CREATE
サーバー SQL モードが有効である場合、DATA DIRECTORY
および INDEX DIRECTORY
オプションはパーティション定義で許可されません。MySQL 5.6 では、これらのオプションはサブパーティションを定義するときにも許可されません (Bug #42954)。