mysql存储过程按月创建表分区 方式二

这篇文章与mysql存储过程按月创建表分区 方式一 写的是相同的内容,只是在表分区创建方式上不一样。方式一是以less than(‘YYYY-mm-dd’)含引号作为分区格式,这样分区因为含有了引号,再执行sql查询数据属于哪个分区内时,容易产生问题;查询sql:

SELECT partition_name part,partition_description,partition_ordinal_position
from INFORMATION_SCHEMA.partitions
    WHERE TABLE_SCHEMA = SCHEMA() AND TABLE_NAME='表名' and partition_description>='YYYY-mm-dd'

因含有引号在查询时得到的结果永远都是 maxvalue或者null记录。
所有就重新写了这一种分区方式

#--设置mysql自动允许定时任务
set global event_scheduler =1;

#--建日志表
CREATE TABLE `sys_log_storage` (
  `id` bigint(32) NOT NULL COMMENT 'ID',
  `ip` varchar(16) DEFAULT NULL COMMENT '服务器IP',
  `lvl` varchar(16) DEFAULT NULL COMMENT '日志级别',
  `title` varchar(64) DEFAULT NULL COMMENT '标题',
  `content` varchar(1024) DEFAULT NULL,
  `createtime` datetime NOT NULL COMMENT '创建时间',
  `classname` varchar(128) DEFAULT NULL,
  `method` varchar(64) DEFAULT NULL
) ENGINE=InnoDB CHARSET=utf8 COMMENT='日志存储';


#--分区存储过程
create PROCEDURE pro_sys_logByMonth(IN tableName VARCHAR(20),IN timeColName VARCHAR(20))
COMMENT '每月按时添加表分区的存储过程,由定时任务调用'
BEGIN
    DECLARE p_id int;
    DECLARE nextDate date;
    DECLARE lastDate LONG;
    #--获取表中的现有的分区数量数量
    SELECT COUNT(partition_name) into p_id FROM INFORMATION_SCHEMA.partitions 
                                        WHERE TABLE_SCHEMA = SCHEMA() AND TABLE_NAME=tableName;
    if p_id=0 then
        #--获取下个月第一天的时间值,根据此值设置时间分区
        SELECT DATE_ADD(CURDATE()-DAY(CURDATE())+1,INTERVAL 1 MONTH) INTO nextDate  from DUAL;
        set @v_add=CONCAT('ALTER table ',tableName,' PARTITION by range(TO_DAYS(',timeColName,'))
                                    (partition ',CONCAT('par',p_id),' values less than (TO_DAYS(\'',nextDate,'\')))');
    ELSE
        #--获取表中现有的最大的分区日期
        SELECT max(partition_description) des into lastDate from INFORMATION_SCHEMA.partitions 
                                        WHERE TABLE_SCHEMA = SCHEMA() AND TABLE_NAME=tableName;
        SELECT DATE_ADD(FROM_DAYS(lastDate),INTERVAL 1 MONTH) INTO nextDate from DUAL;
        set @v_add=CONCAT('alter table ',tableName,' add partition (partition ',CONCAT('par',p_id),
                                                    ' values less than (TO_DAYS(\'',nextDate,'\')))');
    END IF;
    PREPARE stmt from @v_add;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END


#--每月创建一个分区的定时任务
create event event_sysLog on SCHEDULE EVERY 1 MONTH STARTS CURRENT_TIMESTAMP
on COMPLETION PRESERVE
ENABLE
do call pro_sys_logByMonth('sys_log_storage','createtime');


#--添加联合索引
alter table sys_log_storage add PRIMARY KEY(id,createtime);
alter table sys_log_storage change id id bigint(32) not null auto_increment;
alter table sys_log_storage auto_increment=1;
#--添加索引
alter TABLE sys_log_storage add index inx_syslog_ip(ip);

#--查看sql执行时,查询了那些分区,及使用的索引
EXPLAIN PARTITIONs select * from sys_log_storage  where ip='125.76.249.62' and  createtime <'2016-01-20';

当数据量大时,需要调整分区规则,比如按周或者天,代码如下:

-- 按日期格式自动添加分区存储过程
create PROCEDURE pro_sys_logByWeekDay (IN tableName VARCHAR(20),IN timeColName VARCHAR(20),IN dateFormat VARCHAR(10))
COMMENT '按日期格式(年YEAR,月month,周week,日day)添加表分区的存储过程,由定时任务调用'
BEGIN
    DECLARE p_id int;
    DECLARE lasttime Long;
    DECLARE nexttime varchar(20);
    -- 获取表中现有的最大的分区日期
    SELECT max(partition_ordinal_position),max(partition_description) des into p_id,lasttime from INFORMATION_SCHEMA.partitions WHERE TABLE_SCHEMA = SCHEMA() AND TABLE_NAME=tableName;
    -- lasttime的值是'2015-12-01' 含引号格式的字符串  必须转换成没有引号的字符串
    set @v_add_a=CONCAT('select adddate(from_days(',lasttime,'),Interval 1 ',dateFormat,') into @nexttime from dual ');
    PREPARE stm from @v_add_a;
    EXECUTE stm;
    DEALLOCATE PREPARE stm;
    -- 将编译执行的stm结果存储到lasttimeadd中
    set nexttime=@nexttime; 
    set @v_add=CONCAT('alter table ',tableName,' add partition (partition ',CONCAT('par',p_id),' values less than (TO_DAYS(\'',nexttime,'\')))');
    PREPARE stmt from @v_add;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END

-- 创建每周生成一次表分区的定时任务
create EVENT event_sysLogWeek on SCHEDULE EVERY 1 MONTH STARTS CURRENT_TIMESTAMP
on COMPLETION PRESERVE
ENABLE
DO call  pro_sys_logByWeekDay('sys_log_storage6','createtime','Week');

-- 创建每天生成一次表分区的定时任务
create EVENT event_sysLogDay on SCHEDULE EVERY 1 DAY STARTS CURRENT_TIMESTAMP
on COMPLETION PRESERVE
ENABLE
DO call  pro_sys_logByWeekDay('sys_log_storage6','createtime','day');
发布了25 篇原创文章 · 获赞 46 · 访问量 18万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章