1. 程式人生 > 實用技巧 >mysql資料庫大表加索引

mysql資料庫大表加索引

最近大後臺檢視一些資料統計的時候,很慢,甚至會有超時情況,前端設定的超時時間是20秒。

後來通過檢視日誌和慢查詢,發現一條sql語句執行時間超過18秒,基本都19秒左右。

 select count(*) from tb_name where create_time > xxx;

最終得知是因為這個表資料行數已經超過 一千萬了,然後create_time欄位又沒有索引 。

那解決辦法肯定是加索引嘍。

但是這個表是一直在線上執行,很重要和業務部分。如果給千萬級的大表線上加索引 ,肯定會卡死。

然後就蒐羅了一大筐解決方案,比如 線上無鎖加索引使用

ALTER TABLE tbl_name ADD PRIMARY KEY
(column), ALGORITHM=INPLACE, LOCK=NONE;

後來才發現,這個特性是Mysql 5.6以後才支援,然而我們的mysql用的是5.5版本

最後在 《高效能Mysql》一書中看到,可在通過 “影子拷貝”來解決,

就是先建立一張和源表無關的新表,然後通過重新命名和刪表操作交換兩張表;

#操作步驟:
#1、建立一張和原表結構一樣的空表,只是表名不一樣
    create table tb_name_tmp like tb_name;

#2、把新建的空表非主鍵索引都刪掉,因為這樣在往新表導資料的時候效率會很快(因為除了必要的主鍵以外,不用再去建立其它索引資料了)
alter tb_name_tmp drop index index_name; #3、從舊錶往主表裡導資料,如果資料太大,建議分批匯入,只需確保無重複資料就行,因為匯入資料太大,會很佔用資源(記憶體,磁碟io, cpu等),可能會影響舊錶在線上的業務。我是每批次100萬條資料匯入,基本上每次都是在 20s左右 insert into tb_name_tmp select * from tb_name where id between start_id and end_id; #4、資料導完後,再對新表進行新增索引 create index index_name on tb_name_tmp(column_name);
#5、當大部分資料匯入後,索引也建立好了,但是舊錶資料量還是會因業務的增長而增長,這時候為了確保新舊錶的資料一至性和平滑切換,建議寫一個指令碼,判斷當舊錶的資料行數與新表一致時,就切換。我是以 max(id)來判斷的。 rename table tb_name to tb_name_tmp1; rename table tb_name_tmp to tb_name;

當給新表加完索引後,最上面那條查詢直接就是0.0002s