Fak*_*ala 7 mysql partitioning
我有一个数据库,其中的日期列的数据类型为日期。我在用mysql 5.6
该表预计每天有 10k 行。我想在年份范围的表上创建分区,然后在该特定年份的月份上创建子分区。
我试过的是,
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)
);
Run Code Online (Sandbox Code Playgroud)
我能够在空表上执行上述查询。但是当我插入或在同一个表中使用一些数据执行上述查询时,我收到以下错误。
#1526 - Table has no partition for value 2014
Run Code Online (Sandbox Code Playgroud)
无法理解确切的错误是什么。
另请告诉我子分区是否有助于更好地优化表,或者我应该只使用分区?
更新:我确实能够创建分区。现在的问题是创建了一个 NULL 分区。当我确保没有空日期并且在创建分区时处理了所有日期条件时。
问题是如何查看哪些数据已进入 NULL 分区?这样我就可以了解问题所在。
我使用此查询得到一个空分区名称。
SELECT PARTITION_NAME, TABLE_ROWS, PARTITION_EXPRESSION, PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'nav_master' limit 0,180
Run Code Online (Sandbox Code Playgroud)
使用此查询获取分区中的所有行,问题是传递什么作为 null 的分区名称?
SELECT count(*) FROM nav_master PARTITION(??);
Run Code Online (Sandbox Code Playgroud)
小智 7
我必须做同样的事情,但解决方法略有不同。基本上据我通过阅读文档了解到,MySQL 子分区不支持除HASH和KEY之外的分区类型。
在 MySQL 5.6 中,可以对按 RANGE 或 LIST 分区的表进行子分区。子分区可以使用 HASH 或 KEY 分区。这也称为复合分区。
这意味着我们无法确定记录最终会出现在哪个子分区中。这取决于MySQL。所以我认为给你的子分区(即一月)起这样的名字是不明智的,因为你无法知道那个月创建的东西是否会在那里结束。这是因为您不能按 进行子分区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
Run Code Online (Sandbox Code Playgroud)
从这里的docco来看,语法如下:
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
Run Code Online (Sandbox Code Playgroud)
用于创建带有分区的表。
但是,要添加分区,您必须
ALTER TABLE t1 ADD PARTITION (PARTITION p3 VALUES LESS THAN (2002));
Run Code Online (Sandbox Code Playgroud)
所以,这似乎是一个语法问题 - RTF(ine)Manual :-)
至于你的第二个问题 - 只有你可以回答 - 取决于你的数据量和存储配置。
归档时间: |
|
查看次数: |
50058 次 |
最近记录: |