Mysql 創建存儲過程、事件定時調用存儲過程、表分區及自動分區學習筆記。


當一表數據逐漸變大後,查詢會變得很慢,目前所用的是加索引和表分區,也可以做分表,這個暫時沒用上


記錄下對 已存在的表如何做分區: 


//(一般企業用會把這些過程寫出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: 轉載請附上作者,碼字不易呀~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章