1. 程式人生 > >MySQL定位慢查詢以及索引優化

MySQL定位慢查詢以及索引優化

(一)定位慢查詢
1.通過explain,可以檢視sql語句的執行情況(比如查詢的表,使用的索引以及mysql在表中找到所需行的方式等),一般情況下,基本可以通過explain,主要是通過其查詢行的方式和查詢行數確定問題,因為全表掃描很浪費時間,佔用cpu

2.通過show profiles查找出執行sql語句的query_id,接著執行show profile for query_id 看到執行過程中執行緒的每個狀態的消耗時間,可以獲取最消耗時間的執行緒狀態。在SQL優化中幫助我們瞭解時間消耗都去哪裡了

3.trace命令,檢視優化器是如何選擇執行計劃
1)設定格式為json和trace最大能夠使用的記憶體大小

set optimizer_trace="enabled=on",end_markers_in_json=on;
set optimizer_trace_max_mem_size=100000;

2)檢查information_schema.optimizer_trace,可以得到mysql如何執行sql的

select * from information_schema.optimizer_trace\G

(二)索引優化
一般通過索引優化就能解決大多數的SQL效能問題
索引優化就是建立合理的索引,建立索引的幾條策略(個人覺得更像是規定)
1)獨立的列,即索引列不能是表示式的一部分,也不能是函式的引數
2)字首索引,可以減少索引佔用的記憶體。適用於like ‘xxx%’的sql語句優化
如何確定合適的字首索引長度。
方法一:

select count(*)  as cnt,left(city,x) as pref from city_demo group by pref order by cnt desc limit

前十列的cnt 和

select count(*) as cnt,city as pref from city_demo group by pref order by cnt desc limit

的前十列的值接近,則x為最合適的字首長度。x一般是不會從1開始,應該從一個相對較大的數開始增加,直到找到合適的x
方法二:

select count(distinct left(city, x)) /count(*) as sel1

的值等於

select count(distinct city) /count(*) as sel1

的值,則x為合適的x
其中count(distinct city) /count(*)為索引選擇性。
文字描述什麼是索引選擇性:不重複的索引值和資料表的總記錄數的比值
索引的選擇性越高則查詢效率越高。因為選擇性高的索引可以讓mysql在查詢時過濾掉更多的行。
3)多列索引
在多個列上建立獨立的單獨索引並不能提高mysql的查詢效能,合併索引,使用多個單列索引來定位指定行。但是又不能隨便建立多個索引,索引的順序也會影響到查詢速度。
如果索引有多列,如何確定索引順序?選擇性高的作為索引第一列,如何計算選擇性上面已介紹

(三)使用索引需要注意的問題
資料庫預設使用InnDB作為儲存引擎,而B-Tree是InnoDB索引的預設型別
支援:
1)全值匹配。與索引中的所有列進行匹配
2)匹配最左邊 比如字首索引
3)匹配範圍值 即索引列在一個範圍內
4)精確匹配某一列並範圍匹配另外一列
5)特殊的覆蓋索引
不支援:
1)最左原則:不是從最左列開始。比如索引為index1,index2,index3,而查詢中為index2,index3,則優化器不會選擇索引進行優化操作
2)不能跳過中間列,如果跳過則使用第一列的索引,後面的列將不會使用索引。比如index1,index3,中間跳過了index2
3)如果查詢中有某個列的查詢範圍,則其右邊的所有列都無法使用索引優化查詢
4)以%開頭的like不能使用,如果是這種sql語句,則推薦使用全文索引進行優化
5)資料型別出現隱式轉化。一般當索引為數值型別的字串時才會出現這種小錯誤
6)如果使用索引比全表掃描更慢,則不會使用索引。個人理解:優化器選擇能匹配到sql列的優化語句,再試依次使用優化器去執行sql語句,記錄執行時間,執行時間之間進行比較,同時,也會和不使用索引的sql語句執行時間進行比較。選擇當中最小的一個。
7)用or分割開的條件,如果or前的條件中的列有索引,而後面的列中沒有索引,則不會使用索引

(四)檢視索引使用情況
通過命令:

show status like 'Handle_read'

衡量使用索引的指標,一是 Handler_read_key,代表一個行被索引值讀的次數,越小則代表增加索引得到的效能改善不高,因為索引不常用到。二是Handler_read_rnd_next,越大,則代表查詢執行低效,應該建立索引。