如何利用工具,迅猛定位低效SQL? | 1分鐘系列

《兩個工具分析SQL死鎖》
《SQL空值帶來的大坑》
兩個案例分析,展示了MySQL性能分析工具explain的強大。數據庫

《同一個SQL語句,爲啥性能差別咋就這麼大呢?》
詳細敘述了explain結果中最重要的type字段(鏈接類型)的含義。架構

其實,explain結果中還有一個Extra字段,對分析與優化SQL有很大的幫助,今天花1分鐘簡單和你們聊一聊。ide

數據準備:

create table user (
id int primary key,
name varchar(20),
sex varchar(5),
index(name)
)engine=innodb;
insert into user values(1, 'shenjian','no');
insert into user values(2, 'zhangsan','no');
insert into user values(3, 'lisi', 'yes');
insert into user values(4, 'lisi', 'no');

數聽說明:

用戶表:id主鍵索引,name普通索引(非惟一),sex無索引;
四行記錄:其中name普通索引存在重複記錄lisi;工具

實驗目的:

經過構造各種SQL語句,對explain的Extra字段進行說明,啓發式定位待優化低性能SQL語句。oop

1、【Using where】

如何利用工具,迅猛定位低效SQL? | 1分鐘系列

實驗語句:

explain select * from user where sex='no';

結果說明:

Extra爲Using where說明,SQL使用了where條件過濾數據。

須要注意的是:
(1)返回全部記錄的SQL,不使用where條件過濾數據,大機率不符合預期,對於這類SQL每每須要進行優化;
(2)使用了where條件的SQL,並不表明不須要優化,每每須要配合explain結果中的type(鏈接類型)來綜合判斷;
畫外音:join type在《同一個SQL語句,爲啥性能差別咋就這麼大呢?》一文中有詳細敘述,本文再也不展開。性能

本例雖然Extra字段說明使用了where條件過濾,但type屬性是ALL,表示須要掃描所有數據,仍有優化空間。優化

常見的優化方法爲,在where過濾屬性上添加索引。
畫外音:本例中,sex字段區分度不高,添加索引對性能提高有限。code

2、【Using index】

如何利用工具,迅猛定位低效SQL? | 1分鐘系列

實驗語句:

explain select id,name from user where name='shenjian';

結果說明:

Extra爲Using index說明,SQL所須要返回的全部列數據均在一棵索引樹上,而無需訪問實際的行記錄。
畫外音:The column information is retrieved from the table using only information in the index tree without having to do an additional seek to read the actual row.orm

這類SQL語句每每性能較好。blog

問題來了,什麼樣的列數據,會包含在索引樹上呢?

3、【Using index condition】

如何利用工具,迅猛定位低效SQL? | 1分鐘系列
實驗語句:

explain select id,name,sex from user 
where name='shenjian';

畫外音:該SQL語句與上一個SQL語句不一樣的地方在於,被查詢的列,多了一個sex字段。

結果說明:
Extra爲Using index condition說明,確實命中了索引,但不是全部的列數據都在索引樹上,還須要訪問實際的行記錄。
畫外音:彙集索引,普通索引的底層實現差別,詳見《1分鐘瞭解MyISAM與InnoDB的索引差別》。

這類SQL語句性能也較高,但不如Using index。

問題來了,如何優化爲Using index呢?

4、【Using filesort】

如何利用工具,迅猛定位低效SQL? | 1分鐘系列

實驗語句:

explain select * from user order by sex;

結果說明:

Extra爲Using filesort說明,獲得所需結果集,須要對全部記錄進行文件排序。

這類SQL語句性能極差,須要進行優化。

典型的,在一個沒有創建索引的列上進行了order by,就會觸發filesort,常見的優化方案是,在order by的列上添加索引,避免每次查詢都全量排序。

5、【Using temporary】

如何利用工具,迅猛定位低效SQL? | 1分鐘系列
實驗語句:

explain select * from user group by name order by sex;

結果說明:
Extra爲Using temporary說明,須要創建臨時表(temporary table)來暫存中間結果。

這類SQL語句性能較低,每每也須要進行優化。

典型的,group by和order by同時存在,且做用於不一樣的字段時,就會創建臨時表,以便計算出最終的結果集。

6、【Using join buffer (Block Nested Loop)】

如何利用工具,迅猛定位低效SQL? | 1分鐘系列

實驗語句:

explain select * from user where id in(select id from user where sex='no');

結果說明:

Extra爲Using join buffer (Block Nested Loop)說明,須要進行嵌套循環計算。
畫外音:內層和外層的type均爲ALL,rows均爲4,須要循環進行4*4次計算。

這類SQL語句性能每每也較低,須要進行優化。

典型的,兩個關聯表join,關聯字段均未創建索引,就會出現這種狀況。常見的優化方案是,在關聯字段上添加索引,避免每次嵌套循環計算。

結尾:

explain是SQL優化中最經常使用的工具,搞定type和Extra,explain也就基本搞定了。

  • 《MySQL explain,type分析》進行了常見type分析
    本文進行了常見Extra分析
  • 《兩個工具分析SQL死鎖》和《SQL空值帶來的大坑》是兩篇典型案例分析
  • 《MyISAM與InnoDB的索引差別》是InnoDB和MyISAM索引差別分析
  • 《數據庫索引,究竟是什麼作的?》是索引底層實現分析
    以上幾篇文章,強烈建議你們讀透。
    如何利用工具,迅猛定位低效SQL? | 1分鐘系列

架構師之路-分享技術思路
相關推薦:
《緩衝池(buffer pool),此次完全懂了!》
《寫緩衝(change buffer),此次完全懂了!》

做業:
select id,name where XXX是Using index;
select id,name,sex where XXX是Using index condition;
後者如何優化爲Using index呢?

但願你們有收穫,幫忙再看喲。

相關文章
相關標籤/搜索