MySQL執行計劃複習
阿新 • • 發佈:2018-12-03
MySQL執行計劃分析
Ⅰ、認識執行計劃的每個欄位
([email protected]) [(none)]> desc select 1; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ 1 row in set, 1 warning (0.00 sec)
1.1 id
- 單純的join,id都是1,且從上到下
- subquery、scala subquery都會使id遞增
1.2 select type
- simple
- 不使用union或者subquery的簡單query
- 子查詢被優化器開啟,失效了
- primary
- 使用union結合select時,第一個select type
- subquery的query
- union
- 使用union結合select除了第一個select type為primary,其餘為union(extra中union result是union去掉重複值的臨時表)
- 5.7開始union all不會出現union result,因為不去重
- subquery
- 不是用在from後面的subquery
- 和外部表無關聯
- subquery(標量子查詢)執行計劃沒錯誤,不代表sql執行沒錯(不能超過1行資料,subquery return more than 1 row)
- dependent subquery
- 必須依附於外面的值
- scala subquery(和外部有關係的標量子查詢)
- exists
- derived
- from位置之後的subquery
- derived是生成在記憶體或者臨時表空間中
- 如果derived作驅動表時,要點是減少資料量
- 當作被驅動表時產生auto_key索引,也是以減少資料量為目
- 5.7中optimizer_switch='derived_merge=on'可以把簡單subquery開啟成join
- derived_merge為on時被驅動表的連線條件要有索引,為off時被驅動表結果集要小
- 5.7的derived_merge可能導致子查詢中order by失效
- 5.7以下操作可以防止derived_merge
- unin/union all
- group by
- distinct
- 聚合函式
- limit
- @
- materialized
- 物化,5.7開始in會產生,葉會生成auto_key索引
- in中使用hint QB_NAME,外層使用這個hint
- select /+ semijoin(@sub MATERIALIZATION) / * from t_order t2 where t2.emp_no in (select /+ QB_NAME(sub) / t1.emp_no from dept_emp t1);
1.3 table
- NULL
- 表示不使用任何表
- 使用dual
- extra中出現select tables optimized away,多見於count操作
- 表名或者表的別名
- <derved + id><union + id>
- 臨時表<>裡的數字是id列
- tmp_table_size = max_heap_table_size適當調大
1.4 type
- const
- 使用primary key或者unique key取得一條資料
- eq_ref
- join,且滿足被驅動表的連線條件unique key或者primary key
- ref
- 對索引列做等號判斷
- range
- between in like > <
- 和const的區別在於索引掃描範圍不一樣
- index
- 索引全掃描,比起表全掃描且order by的情情況,但是絕大部分情況下也是優化物件
- 不能使用range,const,ref的情況下,且只查詢索引列,即不回表,使用索引進行排序或者聚合即省略排序
- 索引(a,b),select a from xxx where b = ''; 即聯合索引中前導列不在where條件中,且查詢列在索引中
- 在聚合運算中group by後面的列在索引或者primary key中,且查詢列也在索引中
- all
- 全表掃描
- 大表中查詢超過一半以上的值,效果更好
- 索引失效
- 無索引
- 對索引列加工
- 索引列隱式型別轉換
- 對日期型別進行like '20xxx'
- 單列索引,對數字列進行like '30%'
1.5 possible_keys
- 列出可能用到的索引,對優化沒什麼幫助
- 5.6之後開始支援auto_key
- auto_key就是臨時建立索引,需要消耗一些記憶體和cpu,對tmp_table_size,max_heap_table_size依賴較大
- mysql列大小超過767個位元組,無法生成auto_key
- convert(xxx,資料型別,字符集)
1.6 key
- sql用到的索引
1.7 key_len
- 顯示sql到底使用了多少索引
1.8 ref
- 只有type是ref或者const才會出現內容,沒啥用,不用管
1.9 rows
- MySQL優化器根據統計資訊預估出來的值,不準
1.10 filter
- 和rows一樣是預估值,非100的情況是extra有using where關鍵字,表示從儲存引擎中拿到資料後再加工的比例
- 5.7開始該值比較準確
1.11 Extra
- Distinct
- MySQL在join過程中取出一行之後查詢另一個表時,碰到一行就停止,有點像exsits
- 必須是join
- distinct關鍵字
- select列上只能含有驅動表的欄位
- 使用straight_join hint可以強制改變驅動表
- select tables optimized away
- 查詢中只有min、max的時候出現,有時候count貌似也會出現
- 聯合主鍵,其中任一一個欄位用等值查詢,查出另一個欄位的min或max,且不能包含group by
- Using filesort
- order by, group by且沒使用索引
- 8.0 group by不會出現
- Using index
- 只使用索引不回表就可以查到
- 如果表對應的where條件選擇率不是很好,且一行長度很長,此時課考慮建立包含對應列的索引達到減少物理io的目的
- 延遲join必須使用using index,否則無效
- Using temporary
- sql執行過程中儲存中間結果會使用tempoary table,但無法判斷在記憶體還是disk
- order by,group by未使用索引
- 執行計劃中的select type為derived
- show swssion status like '%tmp%'
- max_heap_table_size和tmp_table_size(不一致時以小的為準)
- Using where
- 一般和filtered,rows一起看
- 表示從儲存引擎中拿到資料再過濾
- rows是儲存引擎中拿資料的預估值,filtered是再過濾的百分比
- Using index condition
- 必須是二級索引才有,且有索引後面部分無法使用時,回表次數很大,效果更好
- optimizer_switch='index_condition_pushdown=on'
- Using MRR
- optimizer_switdch='mrr_cost_based=0ff'
- 回表之前先排序,降低隨機io
- Range checked for each record
- type為all
- 這是優化物件,緊接著用show warnings來定位問題
- Using join buffer(Block Nested Loop)
- optimizer_switch='block_nested_loop=on,batched_key_access=on'
- 被驅動表沒有索引且資料量較少的時候,一般這種情況也是優化物件
Ⅱ、獲取執行中SQL的執行計劃
desc for connection connection_id;