MySQL 千萬級數(shù)據(jù)表 partition 實戰(zhàn)應(yīng)用

目前系統(tǒng)的 Stat 表以每天 20W 條的數(shù)據(jù)量增加,盡管已經(jīng)把超過3個月的數(shù)據(jù) dump 到其他地方,但表中仍然有接近 2KW 條數(shù)據(jù),容量接近 2GB。

Stat 表已經(jīng)加上索引,直接 select … where … limit 的話,速度還是很快的,但一旦涉及到 group by 分頁,就會變得很慢。

據(jù)觀察,7天內(nèi)的 group by 需要 35~50s 左右。運營反映體驗極其不友好。
于是上網(wǎng)搜索 MySQL 分區(qū)方案。發(fā)現(xiàn)網(wǎng)上的基本上都是在系統(tǒng)性地講解 partition 的概念和種類,以及一些實驗性質(zhì)的效果,并不貼近實戰(zhàn)。

通過參考 MySQL手冊以及自己的摸索,最終在當前系統(tǒng)中實現(xiàn)了分區(qū),因為記錄一下。

分區(qū)類型的選擇

Stat 表本身是一個統(tǒng)計報表,所以它的數(shù)據(jù)都是按日期來存放的,并且熱數(shù)據(jù)一般只限于當天,以及7天內(nèi)。所以我選擇了 Range 類型來進行分區(qū)。

為當前表創(chuàng)建分區(qū)

因為是對已有表進行改造,所以只能用 alter 的方式:

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點要注意:

一是 p0 分區(qū),這是因為 MySQL(我是5.7版) 有個 bug,就是不管你查的數(shù)據(jù)在哪個區(qū),它都會掃一下第一個區(qū),我們每個區(qū)的數(shù)據(jù)都有幾十萬條,掃一下很是肉疼啊,所以為了避免不必要的掃描,直接弄個0數(shù)據(jù)分區(qū)就行了。

二是 pm 分區(qū),這個是最大分區(qū)。假如不要 pm,那你存 2019-02-15 的數(shù)據(jù)就會報錯。所以 pm 實際上是給未來的數(shù)據(jù)一個預(yù)留的分區(qū)。

定期擴展分區(qū)

由于 MySQL 的分區(qū)并不能自己動態(tài)擴容,所以我們要寫個代碼為它動態(tài)的增加分區(qū)。

增加分區(qū)需要用到 REORGANIZE 命令,它的作用是對某個分區(qū)重新分配。
比如明天是 15 號,那我們要給 15 號也增加個分區(qū),實際上就是把 pm 分區(qū)拆分成2個分區(qū):

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

這里就涉及到一個問題,即如何獲得當前表的所有分區(qū)?網(wǎng)上有挺多方法,但我試了下感覺還是先 show create table stat 然后用正則匹配出所有分區(qū)更方便一點。

定期刪除分區(qū)

隨著數(shù)據(jù)庫越來越大,我們肯定是要清除舊的數(shù)據(jù),同時也要清除舊的分區(qū)。
這個也比較簡單:

ALTER TABLE stat DROP PARTITION p190214, p190215
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容