データ型が日付である日付列を持つデータベースがあります。使ってます mysql 5.6
テーブルには、毎日1万行あると予想されます。テーブルに年の範囲でパーティションを作成し、その特定の年の月にサブパーティションを作成したいと思います。
私が試したのは、
ALTER TABLE nav_master
PARTITION BY RANGE( YEAR(nav_date) )
SUBPARTITION BY HASH( MONTH(nav_date) )
SUBPARTITIONS 12 (
PARTITION january VALUES LESS THAN (2),
PARTITION february VALUES LESS THAN (3),
PARTITION march VALUES LESS THAN (4),
PARTITION april VALUES LESS THAN (5),
PARTITION may VALUES LESS THAN (6),
PARTITION june VALUES LESS THAN (7),
PARTITION july VALUES LESS THAN (8),
PARTITION august VALUES LESS THAN (9),
PARTITION september VALUES LESS THAN (10),
PARTITION october VALUES LESS THAN (11),
PARTITION november VALUES LESS THAN (12),
PARTITION december VALUES LESS THAN (13)
);
空のテーブルで上記のクエリを実行できます。しかし、挿入するとき、またはいくつかのデータを含む同じテーブルで上記のクエリを実行すると、次のエラーが発生します。
#1526 - Table has no partition for value 2014
正確なエラーを理解できません。
また、サブパーティションがテーブルの最適化に役立つか、パーティションを使用する必要があるかどうかも教えてください。
更新:パーティションを実際に作成できました。問題はNULLパーティションが作成されていることです。NULL日付がないことを確認すると、パーティションの作成中にすべての日付条件が処理されました。 =
問題は、どのデータがNULLパーティションに移動したかをどのように確認できるかです。問題が何であるかについてのアイデアを得ることができるように。
このクエリを使用してnullパーティション名を取得しています。
SELECT PARTITION_NAME, TABLE_ROWS, PARTITION_EXPRESSION, PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'nav_master' limit 0,180
このクエリを使用してパーティション内のすべての行を取得する場合、問題はnullのパーティション名として何を渡すかです。
SELECT count(*) FROM nav_master PARTITION(??);
私は同じことをしなければならず、少し異なって解決しました。基本的に、ドキュメントを読んで理解している限り、MySQLサブパーティションは[〜#〜] hash [〜#〜]と[〜#〜] key [〜#以外のパーティションタイプをサポートしていません。 〜]。
MySQL 5.6では、RANGEまたはLISTによってパーティション化されたテーブルをサブパーティション化することが可能です。サブパーティションはHASHまたはKEYパーティショニングを使用できます。これは、複合パーティション分割とも呼ばれます。
これは、レコードがどのサブパーティションで終了するかを判断できないことを意味します。 MySQL次第です。したがって、その月に作成されたものが最終的にそこに到達するかどうかを知る方法がないので、サブパーティション(1月など)にそのような名前を付けるのは賢明ではないと思います。これは、MONTH(nav_date)
ではサブパーティション化できず、HASH(MONTH(nav_date))
またはKEY(MONTH(nav_date))
でのみサブパーティション化できるためです。
そのため、問題を解決するために、テーブルに新しいmonth
列を作成することを決定し、その列にインデックスを追加しました。次に、サブパーティション名を気にせずにKEY(month)
でサブパーティション化しました。このようにMySQL 5.6では、[〜#〜] from [〜#〜]句からメインパーティションを選択し、[〜#〜]で月を指定することでサブパーティションを選択できます。 where [〜#〜]句。
完全な例に従います:
CREATE TABLE `my_example` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`value` double DEFAULT NULL,
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
`timestamp` datetime NOT NULL,
`last_modified` datetime NOT NULL,
`month` tinyint(1) NOT NULL,
PRIMARY KEY (`id`,`timestamp`, `month`),
KEY `in_is_deleted` (`is_deleted`),
KEY `in_last_modified` (`last_modified`),
KEY `in_timestamp` (`timestamp`),
KEY `in_month` (`month`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
PARTITION BY RANGE (YEAR(`timestamp`))
SUBPARTITION BY KEY (`month`)
SUBPARTITIONS 12 (
PARTITION p2011 VALUES LESS THAN (2012),
PARTITION p2012 VALUES LESS THAN (2013),
PARTITION p2013 VALUES LESS THAN (2014),
PARTITION p2014 VALUES LESS THAN (2015),
PARTITION p2015 VALUES LESS THAN (2016),
PARTITION p2016 VALUES LESS THAN (2017),
PARTITION p2017 VALUES LESS THAN (2018),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
EXPLAIN PARTITIONS SELECT * FROM my_example PARTITION (p2015); -- will go through all twelve subpartitions
EXPLAIN PARTITIONS SELECT * FROM my_example PARTITION (p2015) WHERE month = 9; -- will look only into one subpartition
Docco here の構文は次のとおりです。
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
パーティションを持つテーブルを作成するため。
しかし、addパーティションにするには、
ALTER TABLE t1 ADD PARTITION (PARTITION p3 VALUES LESS THAN (2002));
したがって、構文の問題のようです-RTF(ine)Manual :-)
2番目の質問については、データボリュームとストレージ構成に応じて、あなたしか答えられません。
残念ながら、「2014-01-01」より大きいnav_dateを挿入したため、パーティションはこれより大きい日付を受け入れません。この状態では、2013未満の値のみが分割されているためです。
したがって、別のパーティションを追加してテーブルを変更します。