在MySQL 5.7中,有2种基于时间范围或间隔的分区方案,可以根据实际业务需要进行选择。
本文提供了针对DATE、TIME、DATETIME、TIMESTAMP 列如何正确进行时间分区的示例
RANGE分区
针对DATE、TIME或DATETIME列的分区
通过RANGE对表进行分区,对于分区表达式,使用一个函数操作DATE、TIME或DATETIME列并返回一个整数值,如下所示:
CREATE TABLE members (
firstname VARCHAR(25) NOT NULL,
lastname VARCHAR(25) NOT NULL,
username VARCHAR(16) NOT NULL,
email VARCHAR(35),
joined DATE NOT NULL
)
PARTITION BY RANGE( YEAR(joined) ) (
PARTITION p0 VALUES LESS THAN (1960),
PARTITION p1 VALUES LESS THAN (1970),
PARTITION p2 VALUES LESS THAN (1980),
PARTITION p3 VALUES LESS THAN (1990),
PARTITION p4 VALUES LESS THAN MAXVALUE
);
针对TIMESTAMP列的分区
注意:不要采用这种写法,这种写法有BUG的PARTITION BY RANGE (TO_DAYS(entry_end_time)) ( PARTITION p733636 VALUES LESS THAN (733636) ENGINE = InnoDB, PARTITION p733638 VALUES LESS THAN (733638) ENGINE = InnoDB,
使用UNIX_TIMESTAMP()函数,根据TIMESTAMP列的值对表进行RANGE分区,正确示例如下:
CREATE TABLE quarterly_report_status (
report_id INT NOT NULL,
report_status VARCHAR(20) NOT NULL,
report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) (
PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ),
PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ),
PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ),
PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ),
PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ),
PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ),
PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ),
PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ),
PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ),
PARTITION p9 VALUES LESS THAN (MAXVALUE)
);
RANGE COLUMNS 分区
基于RANGE COLUMNS,使用使用DATE或DATETIME列作为分区列对表进行分区
注意:RANGE COLUMNS 这种方式仅仅支持DATE或DATETIME的列作为分区列。
基于datetime类型字段按月分区
-- 创建表
drop table if exists month_report;
CREATE TABLE month_report (
id INT NOT NULL,
status VARCHAR(20) NOT NULL,
updated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
PARTITION BY RANGE COLUMNS(updated ) (
PARTITION p202111 VALUES LESS THAN ( '2021-12-01 00:00:00'),
PARTITION p202112 VALUES LESS THAN ( '2022-01-01 00:00:00'),
PARTITION p202201 VALUES LESS THAN ( '2022-02-01 00:00:00'),
PARTITION p202202 VALUES LESS THAN ( '2022-03-01 00:00:00'),
PARTITION p202203 VALUES LESS THAN ( '2022-04-01 00:00:00')
);
-- 定义存储过程
drop PROCEDURE if EXISTS load_data;
delimiter $$
CREATE PROCEDURE load_data (in num int)
BEGIN
DECLARE v INT DEFAULT 0;
WHILE v < num DO
INSERT INTO month_report VALUES (v, v%2,date_add('2021-12-30 00:00:00', interval v hour) );
SET v = v + 1;
END WHILE;
END$$
delimiter ;
-- 调用存储过程
call load_data(1000)
基于date类型字段按月分区
-- 创建表
drop table if exists month_report2;
CREATE TABLE month_report2 (
id INT NOT NULL,
status VARCHAR(20) NOT NULL,
updated DATE NOT NULL
)
PARTITION BY RANGE COLUMNS(updated ) (
PARTITION p202111 VALUES LESS THAN ( '2021-12-01'),
PARTITION p202112 VALUES LESS THAN ( '2022-01-01'),
PARTITION p202201 VALUES LESS THAN ( '2022-02-01'),
PARTITION p202202 VALUES LESS THAN ( '2022-03-01'),
PARTITION p202203 VALUES LESS THAN ( '2022-04-01')
);
-- 定义存储过程
drop PROCEDURE if EXISTS load_data;
delimiter $$
CREATE PROCEDURE load_data (in num int)
BEGIN
DECLARE v INT DEFAULT 0;
WHILE v < num DO
INSERT INTO month_report2 VALUES (v, v%2,date_add('2021-12-30', interval v day) );
SET v = v + 1;
END WHILE;
END$$
delimiter ;
-- 调用存储过程
call load_data(50)
如何查看分区
select partition_name, partition_expression, table_rows from information_schema.partitions where table_schema = schema() and table_name='month_report'
参考
mysql built-in-function-reference
mysql partitioning-range