歡迎光臨
每天分享高質量文章

讀懂 MySQL 執行計劃

來源:鞠騫的部落格

www.andyqian.com/2017/11/01/database/MySQLplain/

前言

在之前的面試過程中,問到執行計劃,有很多童鞋不知道是什麼?甚至將執行計劃與執行時間認為是同一個概念。今天我們就一起來瞭解一下執行計劃到底是什麼?有什麼用途?

執行計劃是什麼?

執行計劃,簡單的來說,是SQL在資料庫中執行時的表現情況,通常用於SQL效能分析,最佳化等場景。在MySQL使用 explain 關鍵字來檢視SQL的執行計劃。如下所示:

//1. 查詢t_base_user

select * from t_base_user where name=“andyqian”;

 

//2. 檢視上述陳述句的執行計劃

explain select * from t_base_user where name=“andyqian”;

執行檢視上述2陳述句後,我們可以得出以下執行計劃結果



上面執行計劃是什麼意思呢?有什麼參考價值呢?

上面這個執行計劃給到的資訊是: 這個結果透過一個簡單的陳述句全表掃描,共掃描1行,使用where條件在t_base_user表中篩選出的。發現該陳述句並沒有走索引,為什麼是這樣的呢?別急,我們緊接著看下一節。

讀懂執行計劃

透過上面,我們知道了什麼是執行計劃,也看到了執行計劃到底是什麼東西,現在我們來具體瞭解一下,MySQL執行計劃中,每個屬性代表的是什麼意思?

我們一一來介紹,並說明每個屬性有哪些可選值,以及每個可選值的意思。


  • id
    表示查詢中select操作表的順序,按順序從大到依次執行

  • select_type :
    該表示選擇的型別,可選值有: SIMPLE(簡單的),

  • type :
    該屬性表示訪問型別,有很多種訪問型別。
    最常見的其中包括以下幾種: ALL(全表掃描), index(索引掃描),range(範圍掃描),ref (非唯一索引掃描),eq_ref(唯一索引掃描,),(const)常數取用, 訪問速度依次由慢到快。其中 : range(範圍)常見與 between and …, 大於 and 小於這種情況。
    提示 : 慢SQL是否走索引,走了什麼索引,也就可以透過該屬性查看了。

  • table :
    表示該陳述句查詢的表

  • possible_keys :
    顧名思義,該屬性給出了,該查詢陳述句,可能走的索引,(如某些欄位上索引的名字)這裡提供的只是參考,而不是實際走的索引,也就導致會有possible_Keys不為null,key為空的現象。

  • key :
    顯示MySQL實際使用的索引,其中就包括主鍵索引(PRIMARY),或者自建索引的名字。

  • key_len :
    表示索引所使用的位元組數,

  • ref :
    連線匹配條件,如果走主鍵索引的話,該值為: const, 全表掃描的話,為null值

  • rows :
    掃描行數,也就是說,需要掃描多少行,採能獲取標的行數,一般情況下會大於傳回行數。通常情況下,rows越小,效率越高, 也就有大部分SQL最佳化,都是在減少這個值的大小。註意:  理想情況下掃描的行數與實際傳回行數理論上是一致的,但這種情況及其少,如關聯查詢,掃描的行數就會比傳回行數大大增加)

  • Extra
    這個屬性非常重要,該屬性中包括執行SQL時的真實情況資訊,如上面所屬,使用到的是”using where”,表示使用where篩選得到的值,常用的有:
    “Using temporary”: 使用臨時表 “using filesort”: 使用檔案排序


看到這裡,我們應該已經發現,在第一步中,我們的這條SQL

select * from t_base_user where name=”andyqian”;


是沒有走索引的,而且還是全表掃描,在資料量少的情況下,問題還不會特別突出,如果資料量比較大,這可是個會造成生產事故的慢查詢哦,現在我們改造一下,將name欄位新增上索引,

# 新增索引

alter table t_base_user add index idx_name(name);

看看它的執行計劃是怎樣的。

你看,現在已經走idx_name索引了,其type從All(全表掃描)到ref(非唯一索引了),別看就只有這一點點小區別,在大資料量的時候,可是會起大作用的哦。

資料結

本文中演示的資料結構如下:

# 建立表  

create table t_base_user(

oid bigint(20) not null primary key auto_increment,

name varchar(30) null comment “name”,

email varchar(30) null comment “email”,

age int null comment “age”,

telephone varchar(30) null comment “telephone”,

status tinyint(4) null comment “0  無效 1 有效”,

created_at datetime null comment “”,

updated_at datetime null comment “”

)

 

## 新增記錄:

insert into t_base_user(name,email,age,telephone,created_at,updated_at)values(“andyqian”,“andytohome@gmail.com”,20,“15608411”,now(),now());

)

最後

一個好的資料庫表設計,從一開始就應該考慮新增索引,而不是到最後發現慢SQL了,影響業務了,才來補救。其實我在工作經歷當中,由於新建表,或新加欄位後,忘記新增索引也造成了多次生產事故,記憶猶新!!!


其實新建索引也是有一定的原則的,建什麼索引,建在哪些欄位上,這裡面還有不少知識呢,下一篇文章寫,盡請期待吧!


●編號414,輸入編號直達本文

●輸入m獲取文章目錄

推薦↓↓↓

 

Linux學習

更多推薦18個技術類微信公眾號

涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。

贊(0)

分享創造快樂