背景
最近領導分配了個任務,測試sit環境一些功能相比之前慢了許多,需要優化一下。
問題排查過程
瀏覽器F12查看相關接口的響應,看到底是哪個接口反應慢,根據互聯網的要求,頁面3秒還沒有顯示出來,用戶體驗會非常差。
查看相關代碼的提交時間,這些代碼一上線就沒有改動過,由此以我三年職業生涯的經驗推斷,可能是接口相關數據庫表設計不合理或者需要優化導致的問題,因而該篇文章由此誕生!
數據庫單表優化步驟
設計表時:1.選擇合適的字段類型
2.創建高性能索引
運維期間: 1.慢sql優化
2.mysql參數調優
3.數據碎片與索引碎片優化
之前我已做過數據庫部分優化,今天我們所採用的的優化方案是:數據碎片與索引碎片優化
Q:爲什麼會產生數據碎片與索引碎片呢?
A:由於表記錄delete後,只是在相應記錄上表示該記錄被刪除出,表空間沒有釋放從而導致數據碎片和索引碎片,佔用服務器存儲空間和影響索引的效率。
mysql引擎:
MyISAM引擎: 數據儲存在MYD文件中,索引儲存在MYI文件中
InnoDB引擎:frm文件存儲表結構,idb文件儲存索引和數據
數據碎片優化步驟
查看ide庫下需要優化的相關表sql:
select table_name,data_free from information_schema.tables where table_schema='ide' order by a.data_free desc;可以看到每個表的數據碎片分別是多少,如圖所示:
我們可以看到:rdos_engine_job_cache表的數據碎片比較多,可以清理一下
查看清理前表相關文件的大小,數據和索引文件是49452,如圖所示:
也可以用sql查詢:數據大小如上上圖的data_length,和data_free之和。
索引大小:show index from rdos_engine_job_cache;
Cardinality:索引中唯一值的數目的估計值。通過運行ANALYZE TABLE或myisamchk -a可以更新。基數根據被存儲爲整數的統計數據來計數,所以即使對於小型表,該值也沒有必要是精確的。基數越大,當進行聯合時,MySQL使用該索引的機會就越大。
相關字段值老鐵們可以自行百度。
注意:在OPTIMIZE TABLE運行過程中,MySQL會鎖定表。
對於myisam可以直接使用 optimize table table.name, 當是InnoDB引擎時,會報“Table does not support optimize, doing recreate + analyze instead”,一般情況下,由myisam轉成innodb,會用alter table table.name engine='innodb'進行轉換,優化也可以用這個。所以當是InnoDB引擎時我們就用alter table table.name engine='innodb'來代替optimize做優化就可以。
我們的表用的是Innodb引擎,執行命令:alter table rdos_engine_job_cache engine='innodb';如圖所示:
由圖可以看到清理前後的對比:表空間確實釋放了不少
索引碎片優化步驟
Analyze Table
MySQL 的Optimizer(優化元件)在優化SQL語句時,首先需要收集一些相關信息,其中就包括表的cardinality(可以翻譯爲“散列程度”),它表示某個索引對應的列包含多少個不同的值——如果cardinality大大少於數據的實際散列程度,那麼索引就基本失效了。
我們可以使用SHOW INDEX語句來查看索引的散列程度:
SHOW INDEX FROM PLAYERS;
TABLE KEY_NAME COLUMN_NAME CARDINALITY
------- -------- ----------- -----------
PLAYERS PRIMARY PLAYERNO 14
因爲此時PLAYER表中不同的PLAYERNO數量遠遠多於14,索引基本失效。
下面我們通過Analyze Table語句來修復索引:
ANALYZE TABLE PLAYERS;
SHOW INDEX FROM PLAYERS;
結果是:
TABLE KEY_NAME COLUMN_NAME CARDINALITY
------- -------- ----------- -----------
PLAYERS PRIMARY PLAYERNO 1000
此時索引已經修復,查詢效率大大提高。
需要注意的是,如果開啓了binlog,那麼Analyze Table的結果也會寫入binlog,我們可以在analyze和table之間添加關鍵字local取消寫入。