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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章