按日期分区非常大 table - MySQL
Partition very large table by date - MySQL
我想在 MySQL 中的日期格式列上创建一个带有分区的 table,并且希望每次添加额外的日期(每天)时更新分区。
最好的方法是什么?为此使用的代码是什么?
提前致谢
举个简单的例子:
CREATE TABLE `test`.`NewTable` (
`id` INT NOT NULL AUTO_INCREMENT,
`created` DATETIME NULL,
PRIMARY KEY (`id`,`created`)
);
ALTER TABLE `test`.`NewTable`
PARTITION BY RANGE (TO_DAYS(`Created`)) (
PARTITION `20150531` VALUES LESS THAN (TO_DAYS('2015-06-01 00:00:00')),
PARTITION `20150601` VALUES LESS THAN (TO_DAYS('2015-06-02 00:00:00')),
PARTITION `20150602` VALUES LESS THAN MAXVALUE
);
这为您提供了一个包含三个分区的 table:
20150531
= 6 月 1 日之前的所有 [旧] 数据
20150601
= 6 月 1 日的所有数据
20150602
= 6 月 1 日之后的所有 [FUTURE] 数据(或未来时间戳不正确)
在 6 月 2 日开始时,您想要创建一个新分区来保存 6 月 2 日的所有数据。
为此,您需要将 20150602
分区分成两个分区。
20150602
6 月 2 日以来的所有数据
20150603
对于 6 月 2 日之后的所有 [FUTURE] 数据(或未来时间戳不正确)
这是通过以下方式完成的:
ALTER TABLE `test`.`NewTable`
REORGANIZE PARTITION 20150602 INTO (
PARTITION 20150602 VALUES LESS THAN (TO_DAYS('2015-06-03 00:00:00')),
PARTITION 20150603 VALUES LESS THAN MAXVALUE
);
这样你就可以使用:
SELECT MAX(PARTITION_NAME) FROM INFORMATION_SCHEMA.partitions
WHERE TABLE_SCHEMA = 'test'
AND TABLE_NAME = 'NewTable';
获取您的 FUTURE 分区,从那里应该可以直接计算出下一个分区需要的内容。
我为此使用的事件:
DROP EVENT AddNewPartition_daily;
DELIMITER $$
CREATE EVENT AddNewPartition_daily
ON SCHEDULE
EVERY 1 DAY STARTS CONCAT(DATE_SUB(CURDATE(), INTERVAL -1 DAY),' 00:00:01')
ON COMPLETION PRESERVE
COMMENT 'Adds a New Partition to the Top, and Removes the Oldest Partition From NewTable'
DO
BEGIN
SET @MinP := (SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 9 DAY),'%Y%m%d'));
SET @MaxP := (SELECT MAX(PARTITION_NAME) FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'NewTable');
SET @Today := (SELECT CONCAT(CURDATE(),' 00:00:00'));
SET @Tomorrow := (SELECT CONCAT(DATE_SUB(CURDATE(), INTERVAL -1 DAY),' 00:00:00'));
SET @TodP := (SELECT DATE_FORMAT(CURDATE(),'%Y%m%d'));
SET @TomP := (SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL -1 DAY),'%Y%m%d'));
#ADD NEW PARTITION TO TOP
SET @SQL1 := CONCAT('
ALTER TABLE test.NewTable
REORGANIZE PARTITION `',@TodP,'` INTO
(
PARTITION `',@TodP,'` VALUES LESS THAN (TO_DAYS(\'',@Tomorrow,'\')),
PARTITION `',@TomP,'` VALUES LESS THAN MAXVALUE
)');
PREPARE stmt FROM @SQL1;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
#REMOVE OLDEST PARTITION
SET @SQL2 := CONCAT('ALTER TABLE test.NewTable DROP PARTITION `',@MinP,'`');
PREPARE stmt FROM @SQL2;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
您应该注意,如果您只是不断添加分区而不删除它们,最终会影响性能
我想在 MySQL 中的日期格式列上创建一个带有分区的 table,并且希望每次添加额外的日期(每天)时更新分区。
最好的方法是什么?为此使用的代码是什么?
提前致谢
举个简单的例子:
CREATE TABLE `test`.`NewTable` (
`id` INT NOT NULL AUTO_INCREMENT,
`created` DATETIME NULL,
PRIMARY KEY (`id`,`created`)
);
ALTER TABLE `test`.`NewTable`
PARTITION BY RANGE (TO_DAYS(`Created`)) (
PARTITION `20150531` VALUES LESS THAN (TO_DAYS('2015-06-01 00:00:00')),
PARTITION `20150601` VALUES LESS THAN (TO_DAYS('2015-06-02 00:00:00')),
PARTITION `20150602` VALUES LESS THAN MAXVALUE
);
这为您提供了一个包含三个分区的 table:
20150531
= 6 月 1 日之前的所有 [旧] 数据
20150601
= 6 月 1 日的所有数据
20150602
= 6 月 1 日之后的所有 [FUTURE] 数据(或未来时间戳不正确)
在 6 月 2 日开始时,您想要创建一个新分区来保存 6 月 2 日的所有数据。
为此,您需要将 20150602
分区分成两个分区。
20150602
6 月 2 日以来的所有数据
20150603
对于 6 月 2 日之后的所有 [FUTURE] 数据(或未来时间戳不正确)
这是通过以下方式完成的:
ALTER TABLE `test`.`NewTable`
REORGANIZE PARTITION 20150602 INTO (
PARTITION 20150602 VALUES LESS THAN (TO_DAYS('2015-06-03 00:00:00')),
PARTITION 20150603 VALUES LESS THAN MAXVALUE
);
这样你就可以使用:
SELECT MAX(PARTITION_NAME) FROM INFORMATION_SCHEMA.partitions
WHERE TABLE_SCHEMA = 'test'
AND TABLE_NAME = 'NewTable';
获取您的 FUTURE 分区,从那里应该可以直接计算出下一个分区需要的内容。
我为此使用的事件:
DROP EVENT AddNewPartition_daily;
DELIMITER $$
CREATE EVENT AddNewPartition_daily
ON SCHEDULE
EVERY 1 DAY STARTS CONCAT(DATE_SUB(CURDATE(), INTERVAL -1 DAY),' 00:00:01')
ON COMPLETION PRESERVE
COMMENT 'Adds a New Partition to the Top, and Removes the Oldest Partition From NewTable'
DO
BEGIN
SET @MinP := (SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 9 DAY),'%Y%m%d'));
SET @MaxP := (SELECT MAX(PARTITION_NAME) FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'NewTable');
SET @Today := (SELECT CONCAT(CURDATE(),' 00:00:00'));
SET @Tomorrow := (SELECT CONCAT(DATE_SUB(CURDATE(), INTERVAL -1 DAY),' 00:00:00'));
SET @TodP := (SELECT DATE_FORMAT(CURDATE(),'%Y%m%d'));
SET @TomP := (SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL -1 DAY),'%Y%m%d'));
#ADD NEW PARTITION TO TOP
SET @SQL1 := CONCAT('
ALTER TABLE test.NewTable
REORGANIZE PARTITION `',@TodP,'` INTO
(
PARTITION `',@TodP,'` VALUES LESS THAN (TO_DAYS(\'',@Tomorrow,'\')),
PARTITION `',@TomP,'` VALUES LESS THAN MAXVALUE
)');
PREPARE stmt FROM @SQL1;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
#REMOVE OLDEST PARTITION
SET @SQL2 := CONCAT('ALTER TABLE test.NewTable DROP PARTITION `',@MinP,'`');
PREPARE stmt FROM @SQL2;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
您应该注意,如果您只是不断添加分区而不删除它们,最终会影响性能