MySQL按天或按月分區

MySQL表分區

前言

表數據量過大時(一般指超過500萬條)時可以考慮分區或分表方式。

相比分表,分區更爲簡單,不需要對錶的列進行拆分,應用程序不需要修改,也不需要引入分表分庫的中間件。

表分區

常見的表分區是根據用戶id、或區域,或日期進行分區。

根據日期進行分區

常見按天或按月進行分區,取決於每個分區的數據量大小。

查看數據庫是否支持分區

show variables like '%partition%';

查看錶分區定義

show create table <table>;

增加分區

作爲分區的字段必須爲主鍵或唯一索引的一部分。

按天進行分區:

ALTER TABLE <table> ADD PARTITION BY RANGE (to_days(visit_date))
  (
    PARTITION p_20200401 VALUES LESS THAN (to_days('2020-04-02')),
    PARTITION p_20200402 VALUES LESS THAN (to_days('2020-04-03')),
    PARTITION p_20200403 VALUES LESS THAN (to_days('2020-04-04')),
    PARTITION p_20200404 VALUES LESS THAN (to_days('2020-04-05')),
    PARTITION p_20200405 VALUES LESS THAN (to_days('2020-04-06')),
    PARTITION p_20200406 VALUES LESS THAN (to_days('2020-04-07')),
    PARTITION p_20200407 VALUES LESS THAN (to_days('2020-04-08')),
    PARTITION p_20200408 VALUES LESS THAN (to_days('2020-04-09')),
    PARTITION p_20200409 VALUES LESS THAN (to_days('2020-04-10')),
    PARTITION p_20200410 VALUES LESS THAN (to_days('2020-04-11')),
    PARTITION p_20200411 VALUES LESS THAN (to_days('2020-04-12')),
    PARTITION p_20200412 VALUES LESS THAN (to_days('2020-04-13')),
    PARTITION p_20200413 VALUES LESS THAN (to_days('2020-04-14')),
    PARTITION p_20200414 VALUES LESS THAN (to_days('2020-04-15')),
    PARTITION p_20200415 VALUES LESS THAN (to_days('2020-04-16')),
    PARTITION p_20200416 VALUES LESS THAN (to_days('2020-04-17')),
    PARTITION p_20200417 VALUES LESS THAN (to_days('2020-04-18')),
    PARTITION p_20200418 VALUES LESS THAN (to_days('2020-04-19')),
    PARTITION p_20200419 VALUES LESS THAN (to_days('2020-04-20')),
    PARTITION p_20200420 VALUES LESS THAN (to_days('2020-04-21')),
    PARTITION p_20200421 VALUES LESS THAN (to_days('2020-04-22')),
    PARTITION p_20200422 VALUES LESS THAN (to_days('2020-04-23')),
    PARTITION p_20200423 VALUES LESS THAN (to_days('2020-04-24')),
    PARTITION p_20200424 VALUES LESS THAN (to_days('2020-04-25')),
    PARTITION p_20200425 VALUES LESS THAN (to_days('2020-04-26')),
    PARTITION p_20200426 VALUES LESS THAN (to_days('2020-04-27')),
    PARTITION p_20200427 VALUES LESS THAN (to_days('2020-04-28')),
    PARTITION p_20200428 VALUES LESS THAN (to_days('2020-04-29')),
    PARTITION p_20200429 VALUES LESS THAN (to_days('2020-04-30')),
    PARTITION p_other    VALUES LESS THAN (MAXVALUE)
  );

按月分區:

ALTER TABLE <table> ADD PARTITION BY RANGE (to_days(visit_date))
  (
    PARTITION p_202001 VALUES LESS THAN (to_days('2020-02-01')),
    PARTITION p_202002 VALUES LESS THAN (to_days('2020-03-01')),
    PARTITION p_202003 VALUES LESS THAN (to_days('2020-04-01')),
    PARTITION p_202004 VALUES LESS THAN (to_days('2020-05-01')),
    PARTITION p_202005 VALUES LESS THAN (to_days('2020-06-01')),
    PARTITION p_202006 VALUES LESS THAN (to_days('2020-07-01')),
    PARTITION p_202007 VALUES LESS THAN (to_days('2020-08-01')),
    PARTITION p_202008 VALUES LESS THAN (to_days('2020-09-01')),
    PARTITION p_202009 VALUES LESS THAN (to_days('2020-10-01')),
    PARTITION p_202010 VALUES LESS THAN (to_days('2020-11-01')),
    PARTITION p_202011 VALUES LESS THAN (to_days('2020-12-01')),
    PARTITION p_202012 VALUES LESS THAN (to_days('2021-01-01')),
    PARTITION p_other  VALUES LESS THAN (MAXVALUE)
  );

早期的MySQL版本只支持整數來進行範圍分區,因此需要用to_days()函數將日期轉換爲整數,較新的MySQL已經支持直接根據Date或Datetime類型的列來分區,對Timestamp類型的列還是需要用UNIX_TIMESTAMP() 函數將時間戳轉換爲整數。

參考:

查看執行計劃是否使用了分區

EXPLAIN PARTITIONS SELECT count(1) FROM <table> WHERE visit_date = '2020-04-01';

檢查partitions是否命中了正確的分區。

查看執行計劃

EXPLAIN SELECT count(1) FROM <table> WHERE visit_date = '2020-04-01';

執行計劃說明:

  1. type的性能好壞依次爲:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
  2. 一般要求type性能不應該低於range,最好能達到ref或以上

參考:

參考資料

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