MySQL 千萬級數據表 partition 實戰應用

目前系統的 Stat 表以天天 20W 條的數據量增長,儘管已經把超過3個月的數據 dump 到其餘地方,但表中仍然有接近 2KW 條數據,容量接近 2GB。sql

Stat 表已經加上索引,直接 select … where … limit 的話,速度仍是很快的,但一旦涉及到 group by 分頁,就會變得很慢。數據庫

據觀察,7天內的 group by 須要 35~50s 左右。運營反映體驗極其不友好。 因而上網搜索 MySQL 分區方案。發現網上的基本上都是在系統性地講解 partition 的概念和種類,以及一些實驗性質的效果,並不貼近實戰。spa

經過參考 MySQL手冊以及本身的摸索,最終在當前系統中實現了分區,由於記錄一下。code

分區類型的選擇

Stat 表自己是一個統計報表,因此它的數據都是按日期來存放的,而且熱數據通常只限於當天,以及7天內。因此我選擇了 Range 類型來進行分區。索引

爲當前表建立分區

由於是對已有表進行改造,因此只能用 alter 的方式:string

ALTER TABLE stat
    PARTITION BY RANGE(TO_DAYS(dt)) (
        PARTITION p0 VALUES LESS THAN(0),
        PARTITION p190214 VALUES LESS THAN(TO_DAYS('2019-02-14')),
        PARTITION pm VALUES LESS THAN(MAXVALUE)
    );
複製代碼

這裏有2點要注意:it

一是 p0 分區,這是由於 MySQL(我是5.7版) 有個 bug,就是無論你查的數據在哪一個區,它都會掃一下第一個區,咱們每一個區的數據都有幾十萬條,掃一下非常肉疼啊,因此爲了不沒必要要的掃描,直接弄個0數據分區就好了。io

二是 pm 分區,這個是最大分區。假如不要 pm,那你存 2019-02-15 的數據就會報錯。因此 pm 其實是給將來的數據一個預留的分區。table

按期擴展分區

因爲 MySQL 的分區並不能本身動態擴容,因此咱們要寫個代碼爲它動態的增長分區。class

增長分區須要用到 REORGANIZE 命令,它的做用是對某個分區從新分配。 好比明天是 15 號,那咱們要給 15 號也增長個分區,實際上就是把 pm 分區拆分紅2個分區:

ALTER TABLE stat
    REORGANIZE PARTITION pm INTO (
        PARTITION p190215 VALUES LESS THAN(TO_DAYS('2019-02-15')),
        PARTITION pm VALUES LESS THAN(MAXVALUE)
    );
複製代碼

這裏就涉及到一個問題,即如何得到當前表的全部分區?網上有挺多方法,但我試了下感受仍是先 show create table stat 而後用正則匹配出全部分區更方便一點。

按期刪除分區

隨着數據庫愈來愈大,咱們確定是要清除舊的數據,同時也要清除舊的分區。 這個也比較簡單:

ALTER TABLE stat DROP PARTITION p190214, p190215
複製代碼
相關文章
相關標籤/搜索