當一表數據逐漸變大後,查詢會變得很慢,目前所用的是加索引和表分區,也可以做分表,這個暫時沒用上
記錄下對 已存在的表如何做分區:
//(一般企業用會把這些過程寫出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: 轉載請附上作者,碼字不易呀~