19.2.6 サブパーティショニング

サブパーティショニング (複合パーティショニングとも呼ばれます) は、パーティション化されたテーブルの各パーティションをさらに分割することです。次の 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 パーティションがあります。これらの各パーティション (p0p1、および 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)。


User Comments
  Posted by Chris Johnson on January 29, 2010
Here is an example of programatically building a sub partitioned table by year and month using PHP.
http://chrisjohnson.blogsite.org/programatically-building-mysql-partitioned-tables/

See link for why I like to name my partitions rather than use system generated names.


<?PHP
$sql
="CREATE TABLE `data_collected` (
`id` int(11) NOT NULL DEFAULT '0',
`sensor_number` int(11) NOT NULL DEFAULT '0',
`data_date` date NOT NULL DEFAULT '0000-00-00',
`data_time` char(4) NOT NULL DEFAULT '',
`value` varchar(255) NOT NULL,
PRIMARY KEY (`id`,`sensor_number`,`data_date`,`data_time`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (YEAR(data_date))
SUBPARTITION BY HASH (MONTH(data_date))
("
;

for(
$i=1994;$i<2012;$i++)
{
$m=$i-1;
$sql.="\nPARTITION p$m VALUES LESS THAN ($i)
(SUBPARTITION s_dec_
$m ENGINE = MyISAM,
SUBPARTITION s_jan_
$m ENGINE = MyISAM,
SUBPARTITION s_feb_
$m ENGINE = MyISAM,
SUBPARTITION s_mar_
$m ENGINE = MyISAM,
SUBPARTITION s_apr_
$m ENGINE = MyISAM,
SUBPARTITION s_may_
$m ENGINE = MyISAM,
SUBPARTITION s_jun_
$m ENGINE = MyISAM,
SUBPARTITION s_jul_
$m ENGINE = MyISAM,
SUBPARTITION s_aug_
$m ENGINE = MyISAM,
SUBPARTITION s_sep_
$m ENGINE = MyISAM,
SUBPARTITION s_oct_
$m ENGINE = MyISAM,
SUBPARTITION s_nov_
$m ENGINE = MyISAM)";
if (
$i!=2011)
$sql.=',';
else
$sql.=")*/";
}

echo 
$sql;
mysql_connect("localhost",'bla','bla');
mysql_select_db("weather");
mysql_query("drop table if exists data_collected");
mysql_query($sql) or die(mysql_error());
?>

  Posted by Тест Босх on March 10, 2011
Previous example is a bad idea. Records wont be pruned. Better use

http://dev.mysql.com/tech-resources/articles/mysql_5.1_partitioning_with_dates.html
Sign Up Login You must be logged in to post a comment.