這篇文章與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');