線上MySQL某個歷史資料表的分割槽筆記

2021-09-20 23:52:42 字數 3809 閱讀 6654

背景:

線上的乙個歷史資料庫,業務方反饋經常遇到乙個範圍查詢就導致cpu迅速飆公升的情況。拿到他們提供的sql後,sql類似下面這種:

select * from `order_his` where `***x` = '222' and `***x` <> 1 and order_time > '2016-11-01 00:00:00' and order_time < '2017-06-01 00:00:00' \g

explain看了下發現基本上是全表掃瞄了,效率太低了,並且他們都是按月查詢的,因此我們就對這張表按月進行分割槽,就能大大減少掃瞄的行數。

注意:timestamp型別的列,只能基於unix_timestamp函式進行分割槽,切記!

### 原始order_his表類似如下這種結構:

create table `order_his` (

`id` int(11) not null auto_increment,

`order_time` timestamp null default null,

`pay_time` timestamp null default null,

`create_time` timestamp null default null,

`update_time` timestamp null default null,

primary key (`id`),

) engine=innodb auto_increment=47603581 default charset=utf8;

step0 建立乙個表結構和原先的表一樣的tmp表

create table `order_his_tmp` like `order_his`;

step1  修改原有的主鍵,將分割槽鍵新增到主鍵裡。

alter table `order_his_tmp` drop primary key,add primary key(id,order_time);

必須把分割槽鍵加到主鍵裡面,不然step2也會報錯提醒你這樣做的。

step2 分割槽操作

alter table `order_his_tmp` partition by range (unix_timestamp (order_time))   

(  partition  p201601  values less than  (unix_timestamp('2016-02-01')) ,

partition  p201602  values less than  (unix_timestamp('2016-03-01')) ,

partition  p201603  values less than  (unix_timestamp('2016-04-01')) ,

partition  p201604  values less than  (unix_timestamp('2016-05-01')) ,

partition  p201605  values less than  (unix_timestamp('2016-06-01')) ,

partition  p201606  values less than  (unix_timestamp('2016-07-01')) ,

partition  p201607  values less than  (unix_timestamp('2016-08-01')) ,

partition  p201608  values less than  (unix_timestamp('2016-09-01')) ,

partition  p201609  values less than  (unix_timestamp('2016-10-01')) ,

partition  p201610  values less than  (unix_timestamp('2016-11-01')) ,

partition  p201611  values less than  (unix_timestamp('2016-12-01')) ,

partition  p201612  values less than  (unix_timestamp('2017-01-01')) ,

partition  p201701  values less than  (unix_timestamp('2017-02-01')) ,

partition  p201702  values less than  (unix_timestamp('2017-03-01')) ,

partition  p201703  values less than  (unix_timestamp('2017-04-01')) ,

partition  p201704  values less than  (unix_timestamp('2017-05-01')) ,

partition  p201705  values less than  (unix_timestamp('2017-06-01')) ,

partition  p201706  values less than  (unix_timestamp('2017-07-01'))

);  

step3、將原先表的資料灌入新的tmp表

insert into `order_his_tmp` select * from `order_his`;

step4、查詢驗證

explain partitions select * from `order_his_tmp` where 

`***x` = '222' and `***x` <> 1 and 

order_time > '2015-11-01 00:00:00' and order_time < '2015-12-21 00:00:00' \g

*************************** 1. row ***************************

id: 1

select_type: ******

table: order_his

partitions: p201511,p201512   ### 可以看到這裡走的是2023年11和12月,這2個分割槽

...........部分內容省略.............

step5、替換原先的表

通知開發同學當前不要對`order_his`表執行查詢操作。

然後我們執行:

rename table `order_his` to `order_his_nopart`;

rename table `order_his_tmp` to `order_his`;

這樣的話,新的`

order_his`表就是分割槽表啦。

step6、新增分割槽表

後期如果需要加分割槽的話,只要執行如下這種操作就可以新增乙個新的分割槽

alter table `order_his` add partition ( partition p201707 values less than (unix_timestamp('2017-08-01'))) ;

當然,如果我們想省事的話,就在step2的時候,一次性多建立很多分割槽(我當時是按月建分割槽,一直建立到2023年)

。此外,也可以寫個儲存過程配合event_schedule每月自動建立乙個新的分割槽。

使用儲存過程的方法這裡先略過,後期補充。

mysql歷史資料 mysql 歷史資料表遷移方案

當業務執行一段時間後,會出現有些表資料量很大,可能對系統效能產生不良的影響,常見的如訂單表 登入log表等,這些資料很有時效性,比如我們一般很少去查上個月的訂單,最多也就是報表統計會涉及到。在我們的資料庫中,使用者登入表就是這種型別的表,一般而言,表中的資料是不可逆的,只有插入操作沒有刪除或者修改操...

mysql 刪除 zabbix歷史資料

zabbix伺服器報警 zabbix housekeeper processes more than 75 busy 原因分析說明 處理方法 vim etc zabbix zabbix server.conf housekeepingfrequency 12 原值是每一小時清理一次,建議改為12或2...

巧用外部表備份歷史資料

在很多的系統中,隨著時間的推移,都會沉澱大量的歷史資料。一般資料量達到一定程度都會考慮使用分割槽表來處理。根據業務規則,可能有些歷史資料隔一段時間就需要做清理了,這個時候歷史資料就需要在分割槽級進行清理。在不同的系統,不同廠商都有不同的實現方案。但是從資料安全角度來說,都需要做備份工作,也是預防萬一...