0
点赞
收藏
分享

微信扫一扫

MySQL基于时间范围分区的2种方案

在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

举报

相关推荐

0 条评论