mysql資料庫大表加索引
阿新 • • 發佈:2020-08-14
最近大後臺檢視一些資料統計的時候,很慢,甚至會有超時情況,前端設定的超時時間是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