# Why is My Query so slow in mysql ###### tags: `note` ## agenda - key - index - query execution plan - Q&A > Q: DB 慢,改設定參數? > A: 有些設定可以加速的,但可能造成當機時會有資料損失 效能影響: query > DB schema > hardware configuration > Mysql configuration > heigh currency ## key ### schema 不必要的資料長度 ex: `name varchar(255)` ![](https://i.imgur.com/td08dyw.png) table 規劃越小越好(依要實作的功能最好作好正規化 ## index index occupy space on disk in memory buffers index maintain 也是需要 i/o 的,所以頻繁更動欄位加 index 也會造成效能問題 ## query execution plan 不必要的 index 過多會導致 query optimizer 混淆,而選擇了錯誤的 index 做查詢 > 且 index 過多會造成 optimizer 判斷時間變長(需實驗一下 複合鍵的情況下,如果 query 條件在 open range(大於小於之類的)之後的判斷式就不會使用到 index EX: ``` index(a, b, c) where a='x' and b>5 and c = 'x' 此時會撈出 `index(a, b, c)` 中的 a='x' and b>5,然後再過濾掉 c = 'x' ``` ### 驗證 index 在查詢時是否用到 -> mysql explain cardinality 值越高代表獨特性越高,時會早較高的 > http://blog.twbryce.com/mysql-explain/ > > ![](https://i.imgur.com/MLcCY64.png) > * type:顯示使用了何種類型。從最優至最差的類型為const、eq_reg、ref、range、indexhe、ALL。 > * possible_keys:顯示可能使用到的索引。此為從WHERE語法中選擇一個適合的欄位名稱。 > * key:實際使用到的索引。如果為NULL,則是沒有使用索引。 > * key_len:使用索引的長度。長度越短 準確性越高。 > * ref:顯示那一列的索引被使用。一般是一個常數(const)。 > * rows:MySQL用來返回資料的筆數。 > * Extra:MySQL用來解析額外的查詢訊息。如果此欄位的值為:Using temporary和Using filesort,表示MySQL無法使用索引。 ## Q&A review 所有用到該張表的 SQL 分析 cardinality 低下的 index(然後其實可以刪除以增加效能 like 的 % 放在前面或後面('xxx%', '%xxx')會有差別 - 'xxx%' 因為可以知道前面的值,所以搜尋欄位可能可以吃到 index - '%xxx' 這類為可能做 full scan,因為前面是模糊搜尋 --- index 越長,成本越高,所以複合式 index 可以的話,可以考慮縮減 index --- merge index OR 條件時 index(a), index(b) where a = 'x' or b = 'x' 此時會`可能`造成 merge index 然後效能會變差(通常效能是比較好的 所以竟量不要設計成會造成 merge index 的 index,不過實際情況還是要依照功能 explain 來分析,optimizer會不會吃到 merge index。 又如果這對搜尋非常頻繁,可以設成複合 index --- 基本上DB 效能優化都是 case by case