線上MySQL某個曆史資料表的分區筆記

來源:互聯網
上載者:User

標籤:線上mysql某個曆史資料表的分區筆記

背景:

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

select * from `order_his` where `xxxx` = ‘222‘ AND `XXXX` <> 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 `xxxx` = ‘222‘ AND `XXXX` <> 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: SIMPLE

        table: order_his

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

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


注意: 當時線上上操作的時候,發現即使做了分區,執行計畫裡面顯示的還是ALL全表掃描了,於是根據這個SELECT 加了個索引解決了這個問題。這裡沒有真實環境不好貼圖出來。



step5、替換原先的表

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

然後我們執行:

rename table `order_his` `order_his_nopart`;

rename table `order_his_tmp` `order_his`;

這樣的話,新的`order_his`表就是分區表啦。




step6、添加分區表

後期如果需要加分區的話,只要執行如下這種操作就可以添加一個新的分區

ALTER TABLE `order_his` ADD PARTITION ( PARTITION P201707 VALUES LESS THAN (UNIX_TIMESTAMP(‘2017-08-01‘))) ;

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

此外,也可以寫個預存程序配合event_schedule每月自動建立一個新的分區。

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


本文出自 “菜雞” 部落格,請務必保留此出處http://lee90.blog.51cto.com/10414478/1917933

線上MySQL某個曆史資料表的分區筆記

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.