当一表数据逐渐变大后,查询会变得很慢,目前所用的是加索引和表分区,也可以做分表,这个暂时没用上
记录下对 已存在的表如何做分区:
//(一般企业用会把这些过程写出sql脚本,丢服务器数据库跑一遍就ok了,还能留底)
对已存在的表做分区,我的做法(以时间为分区的情况):
(1)创建数据结构相同的表, 命名: t_UserCopy
创建表时先定义一个比最早时间早几年的分区,(其实无所谓,反正会删掉,后续补说明)
源表t_user :
id username password createTime
1 程序猿 123456 2019-8-9 00:50
创建t_userCopy
DROP TABLE IF EXISTS `t_UserCopy`;
CREATE TABLE `t_UserCopy` (
`Id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT ,
`username` varchar(100) NOT NULL ,
`password` varchar(100) NOT NULL ,
`createTime` datetime(0) NOT NULL,
PRIMARY KEY (`Id`,`createTime`) USING BTREE,
INDEX `index_createTime`(`createTime`) USING BTREE
)PARTITION BY RANGE (Year(createTime))
(
Partition p2010 Values Less Than ( Year('2011-01-01') )
);
注:我这是按年分,数据多可以按月
分区限制:
• 最大分区数目不能超过1024 >> 按年分能分85年足够了,一般数据过多直接分表了
• 如果含有唯一索引或者主键,则分区列必须包含在所有的唯一索引或者主键在内 >>
PRIMARY KEY (`Id`,`createTime`) USING BTREE, 所以要这样定义主键。至于为什么2010后要定义2011年-01-01呢,ess Than 嘛,顺带学学sql语法
• 不支持外键,既独立表,不能有外键
(2)循环创建表分区
A:插入数据前先做好分区,按年分的话,例如表数据creatTime最早为2017年,那就创建17到2019或2020都行,
我是创建到未来一年,保障点。天知道服务器会不会挂掉重启啥的。
B :在(1)中我们创建了一个p2010的分区,假设我们的t_User 称源表,最早时间为2017年至今,
手动创建不够懒啊,遂:在"存储过程" 中循环对 添加 最早时间 至 未来一年的 分区,用 whiLe 循环创建分区,简单粗暴
DECLARE v_i INT DEFAULT 0;
-- 获取告警最小年份
Select Year(Min(createTime)) Into @min_Year From t_User;
-- 分区至未来 1年
Set v_Count = Year(now()) - @min_Year + 2;
While v_i < v_Count DO
Set v_Year = @min_Year + v_i;
Set v_Sql = CONCAT('Alter Table t_UserCopy Add Partition (Partition P', Cast( v_Year As Char(4)),
' Values Less Than (', Cast((v_Year + 1) As Char(4)), '))');
Set @Sql = v_Sql;
Prepare Cmd From @Sql;
Execute Cmd;
Deallocate Prepare Cmd;
Set v_i = v_i + 1;
End While;
注:若年份大于分区年份,则会报错,因为他不符合你所创建的分区,对号入座,没座位干等就给你打小报告啦
(3) 复源表数据(t_User)到分区表(t_UserCopy),删源表,重命名分区表
INSERT into t_UserCopy SELECT * FROM t_User;
DROP TABLE IF EXISTS `t_User`;
ALTER TABLE t_UserCopy RENAME TO t_User;
注:1:必须在创建了对应的分区后再复制源表数据,住酒店得先预定嘛
2:更新期间产生的数据咋办呢,上级是停服务器搞的,所以我只负责写脚本~但我认为不太好,对于工业上的来说,
一些监控上的告警不会因为你停服务器而不发生告警,即使在夜深人静的时候也可能告警,
停服务器就会丢失数据,虽然一两分钟就能跑完脚本~
想法: A 借助第三方车轮 B...求助大佬
(4) 删除最初分区
-- 删除最初固定分区
Alter table t_UserCopy drop partition p2010;
注:最初分区是为了创建分区表而用,因创建分区表至少要有一个,那就先创建一个再删了就好,(给东家一个面子嘛)
删了无用的分区出于...you konw that
-------------------------- 至此分区的创建及数据的复原已搞定,可时间不等人啊,来个自动分区吧-----------------------------------
(5) 自动创建分区(event事件)
还是懒,不想每年都给它加一个分区吧,来个自动加分区吧,那就用到 event,即事件,定时调用存储过程
这里我让其每个月执行一次,看未来一年的分区是否存在,不存在则添加,存在就:"打扰了大哥,但我下个月还来"。
这是为了减少意外,一年12次都出意外无法执行event的概率极底。
Drop EVENT IF EXISTS `e_createTimePartition_year`;
DELIMITER ;;
CREATE EVENT IF NOT EXISTS e_createTimePartition_year
ON SCHEDULE Every 1 Year STARTS DATE_ADD(DATE_ADD(CURDATE(), INTERVAL 1 Year),INTERVAL 9 HOUR)
ON COMPLETION PRESERVE
DO
Call spAppendPartition_t_User();
;;
注: 1: ON SCHEDULE Every 1 Year STARTS DATE_ADD(DATE_ADD(CURDATE(), INTERVAL 1 Year),INTERVAL 9 HOUR)
是每年分一次,这个是我最初的版本,后改用每月1号00:00执行,(拖了一个月才来记录的(●'◡'●))
又拖了几天: 加个每月1号凌晨执行的定时时间
ON SCHEDULE Every 1 Month STARTS DATE_ADD(DATE_ADD(DATE_SUB(CURDATE(),INTERVAL DAY(CURDATE())-1 DAY), INTERVAL 1 MONTH),INTERVAL 0 HOUR)
2: 分区前得先判断是否存在分区
-- 未来一年
Set v_Year = Year(now()) + 2;
-- 若分区已经存在
If Exists (t_User
Select * From
(
Select Cast(PARTITION_DESCRIPTION As Unsigned Int) As TimeCode From information_schema.`PARTITIONS`
Where
TABLE_SCHEMA = Database() And Lower(Table_Name) = Lower('')
) t
Where t.TimeCode >= v_Year
) Then
Select CONCAT('p',v_Year) as '分区已经存在';
Leave Label_Start;
End If;
(6) 测试自动分区是否能按预期进行:(服务器测试)
一年一次测试的话,一年一年的等就行了,到了明年这个时候来看看,如果你还记得起来的话
So, 在测试服务器上测试,按年的话,上述语法是今天到明年的今天的早时9点,直接去服务器改到明年今天8:59:50
坐等10秒后,查看表分区:
Select PARTITION_NAME From INFORMATION_SCHEMA.PARTITIONS
Where TABLE_SCHEMA=Database() And TABLE_NAME = t_User
伸手党:
修改时间: date -s '20xx-xxchu'fa-xx 08:59:50'
查看数据库时间是否修改成功: mysql> select now();
重置时间: hwclock --hctosys //设置系统时间和硬件时间同步
(8)整合上述的完整脚本,后续再更吧
附上用得上的mysql 查询:
-- 查询所有数据库event事件
select * from mysql.event WHERE db = '数据库名称';
-- 查看分区
SELECT PARTITION_NAME,TABLE_ROWS,PARTITION_EXPRESSION,PARTITION_DESCRIPTION, Table_Name FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA= DATABASE() AND TABLE_NAME = 'AlarmEvent';
-- 分区查询
Select AlarmDateTime From AlarmEvent Partition(p2019);
-- 删除指定分区
alter table AlarmEvent drop partition p2023;
参考文章: https://www.cnblogs.com/zhouguowei/p/9360136.html
Last: 转载请附上作者,码字不易呀~