环境:mysql 5.5
第一:怎么创建表分区
第二:怎么按年月格式(201601)自动创建分区
 
1、创建表,时间字段datetime由于业务需要必须要是unix_timestamp, 由于是按照时间来进行分区的,所以datetime这个字段必须要是主键。否则创建分区的时候会报错。

CREATE TABLE `test` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT ‘主键’, `datetime` int(10) unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘时间’, PRIMARY KEY (`id`,`datetime`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=‘测试表分区’/*!50100 PARTITION BY RANGE (datetime)(PARTITION p201511 VALUES LESS THAN (UNIX_TIMESTAMP(“2015-12-01 00:00:00”)) ENGINE = InnoDB, PARTITION p201512 VALUES LESS THAN (UNIX_TIMESTAMP(“2016-01-01 00:00:00”)) ENGINE = InnoDB) */;

2、创建存储过程,用于下面MYSQL的event定时器调用,自动创建就是event来完成的。这段存储过程的内容就是创建下月分区的意思。


DELIMITER $$

#该表所在数据库名称USE `test`$$DROP PROCEDURE IF EXISTS `create_partition_by_month`$$CREATE PROCEDURE `create_partition_by_month`(IN_SCHEMANAME VARCHAR(64), IN_TABLENAME VARCHAR(64))BEGIN DECLARE ROWS_CNT INT UNSIGNED; DECLARE BEGINTIME TIMESTAMP; DECLARE ENDTIME INT UNSIGNED; DECLARE PARTITIONNAME VARCHAR(16); DECLARE ENDTIME_DATETIME VARCHAR(30); SET BEGINTIME = DATE(NOW()  INTERVAL DAY(NOW()) DAY + INTERVAL 1 DAY + INTERVAL 1 MONTH); SET PARTITIONNAME = DATE_FORMAT( BEGINTIME, ‘p%Y%m’ ); SET ENDTIME = UNIX_TIMESTAMP(BEGINTIME + INTERVAL 1 MONTH); SET ENDTIME_DATETIME = FROM_UNIXTIME(ENDTIME); SELECT COUNT(*) INTO ROWS_CNT FROM information_schema.partitions WHERE table_schema = IN_SCHEMANAME AND table_name = IN_TABLENAME AND partition_name = PARTITIONNAME; IF ROWS_CNT = 0 THEN

SET @SQL = CONCAT( ‘ALTER TABLE `’, IN_SCHEMANAME, ‘`.`’, IN_TABLENAME, ‘`’, ‘ ADD PARTITION (PARTITION ‘, PARTITIONNAME, ” VALUES LESS THAN (UNIX_TIMESTAMP(‘”, 

ENDTIME_DATETIME ,“‘)) ENGINE = InnoDB);” );

PREPARE STMT FROM @SQL; EXECUTE STMT; DEALLOCATE PREPARE STMT; ELSE SELECT CONCAT(“partition `”, PARTITIONNAME, “` for table `”,IN_SCHEMANAME, “.”, IN_TABLENAME, “` already exists”) AS result; END IF;END$$DELIMITER ;

2.1查看已经创建的存储过程。

show procedure status where db=’logtop’;

 
3、创建event。每分钟执行一次,检查下个月的表分区是否已经创建,如果没有创建,则调用上面的存储过程创建。

DELIMITER $$

#该表所在的数据库名称USE `test`$$CREATE EVENT IF NOT EXISTS `e_part_manage`ON SCHEDULE EVERY 1 MINUTE #执行周期,还有天、月等等STARTS ‘2016-01-07 18:27:00’ON COMPLETION PRESERVEENABLECOMMENT ‘Creating partitions’DO BEGIN

#调用刚才创建的存储过程,第一个参数是数据库名称,第二个参数是表名称 CALL test.create_partition_by_month(‘test’,‘test’);END$$DELIMITER ;

3.1查看已经创建的event


SELECT * FROM information_schema.EVENTS;

4、检查MYSQL是否开启event,默认是Off,请设置成On,

SHOW VARIABLES LIKE ‘event_scheduler’ ;
SHOW GLOBAL VARIABLES LIKE ‘event_scheduler’ ;
SET GLOBAL event_scheduler = ON; #打开
只在全局设置的话,当MYSQL重启后该参数又会被重置成Off,所以需要在my.cnf里加上

vim /etc/my.cnf

[mysqld]

event_scheduler=ON

5、插入测试数据


INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-10”));INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-11”));INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-12”));INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-13”));INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-13”));INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-14”));INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-15”));INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-16”));INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-17”));INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-18”));INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-19”));INSERT INTO `test`.`test` (`datetime`) VALUES (unix_timestamp(“2015-12-20”));

6、查看数据在每个分区中的分布情况

SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME=‘test’;

 

#添加分区

ALTER TABLE `test`.`test` ADD PARTITION (PARTITION p201601 VALUES LESS THAN (UNIX_TIMESTAMP(“2016-02-01 00:00:00”)) ENGINE = InnoDB);

#删除分区ALTER TABLE test.testDROP PARTITION p201511;

查看查询SQL是否使用的分区


explain PARTITIONS select *,FROM_UNIXTIME(datetime) from test where datetime > UNIX_TIMESTAMP(“2015-12-10”) and datetime < UNIX_TIMESTAMP(“2015-12-15”);