背景:
線上的乙個歷史資料庫,業務方反饋經常遇到乙個範圍查詢就導致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...
巧用外部表備份歷史資料
在很多的系統中,隨著時間的推移,都會沉澱大量的歷史資料。一般資料量達到一定程度都會考慮使用分割槽表來處理。根據業務規則,可能有些歷史資料隔一段時間就需要做清理了,這個時候歷史資料就需要在分割槽級進行清理。在不同的系統,不同廠商都有不同的實現方案。但是從資料安全角度來說,都需要做備份工作,也是預防萬一...