MYSQL 執(zhí)行計(jì)劃(explain詳解)

使用explain后給出的相關(guān)索引信息

下面是一個(gè)select語(yǔ)句的使用explain之后的例子:

id

select查詢的序列號(hào)

select_type

a.SIMPLE:查詢中不包含子查詢或者UNION
b.PRIMARY:查詢中若包含任何復(fù)雜的子部分,最外層查詢的標(biāo)記
c.SUBQUERY:在SELECT或WHERE列表中包含了子查詢,該子查詢的標(biāo)記
d.DERIVED(衍生):在FROM列表中包含的子查詢的標(biāo)記
e.若第二個(gè)SELECT出現(xiàn)在UNION之后,則被標(biāo)記為UNION;若UNION包含在 FROM子句的子查詢中,外層SELECT將被標(biāo)記為:DERIVED
f.從UNION表獲取結(jié)果的SELECT被標(biāo)記為:UNION RESULT

table

輸出的行所引用的表

type

聯(lián)合查詢所使用的類型,表示MySQL在表中找到所需行的方式,又稱“訪問(wèn)類型”。

type顯示的是訪問(wèn)類型,是較為重要的一個(gè)指標(biāo),結(jié)果值從好到壞依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL ,一般來(lái)說(shuō),得保證查詢至少達(dá)到range級(jí)別,最好能達(dá)到ref。

index: 掃描全部索引樹(shù)
range: 掃描部分索引,索引范圍掃描,對(duì)索引的掃描開(kāi)始于某一點(diǎn),返回匹配值域的行,常見(jiàn)于between、<、>等的查詢
ref: 非唯一性索引掃描,返回匹配某個(gè)單獨(dú)值的所有行。常見(jiàn)于使用非唯一索引即唯一索引的非唯一前綴進(jìn)行的查找
eq_ref:唯一性索引掃描,對(duì)于每個(gè)索引鍵,表中只有一條記錄與之匹配。常見(jiàn)于主鍵或唯一索引掃描
const, system: 當(dāng)MySQL對(duì)查詢某部分進(jìn)行優(yōu)化,并轉(zhuǎn)換為一個(gè)常量時(shí),使用這些類型訪問(wèn)。如將主鍵置于where列表中,MySQL就能將該查詢轉(zhuǎn)換為一個(gè)常量。system是const類型的特例,當(dāng)查詢的表只有一行的情況下, 使用system。
NULL: MySQL在優(yōu)化過(guò)程中分解語(yǔ)句,執(zhí)行時(shí)甚至不用訪問(wèn)表或索引。

possible_keys

指出MySQL能使用哪個(gè)索引在該表中找到行。查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢使用。如果是空的,沒(méi)有相關(guān)的索引。這時(shí)要提高性能,可通過(guò)檢驗(yàn)WHERE子句,看是否引用某些字段,或者檢查字段不是適合索引

key

顯示MySQL實(shí)際決定使用的鍵。如果沒(méi)有索引被選擇,鍵是NULL

key_len

顯示MySQL決定使用的鍵長(zhǎng)度。表示索引中使用的字節(jié)數(shù),可通過(guò)該列計(jì)算查詢中使用的索引的長(zhǎng)度。如果鍵是NULL,長(zhǎng)度就是NULL。文檔提示特別注意這個(gè)值可以得出一個(gè)多重主鍵里mysql實(shí)際使用了哪一部分。

rows

這個(gè)數(shù)表示mysql要遍歷多少數(shù)據(jù)才能找到,表示MySQL根據(jù)表統(tǒng)計(jì)信息及索引選用情況,估算的找到所需的記錄所需要讀取的行數(shù),在innodb上可能是不準(zhǔn)確的

SQL語(yǔ)句的一般執(zhí)行順序

(1)from
(3) join
(2) on
(4) where
(5)group by(開(kāi)始使用select中的別名,后面的語(yǔ)句中都可以使用)
(6) avg,sum....
(7)having
(8) select
(9) distinct
(10) order by

下面來(lái)個(gè)例子幫助記憶

select 考生姓名, max(總成績(jī)) as max總成績(jī)   
  
from tb_Grade   
  
where 考生姓名 is not null   
  
group by 考生姓名   
  
having max(總成績(jī)) > 600   
  
order by max總成績(jī)   

在上面的示例中 SQL 語(yǔ)句的執(zhí)行順序如下:

(1). 首先執(zhí)行 FROM 子句, 從 tb_Grade 表組裝數(shù)據(jù)源的數(shù)據(jù)

(2). 執(zhí)行 WHERE 子句, 篩選 tb_Grade 表中所有數(shù)據(jù)不為 NULL 的數(shù)據(jù)

(3). 執(zhí)行 GROUP BY 子句, 把 tb_Grade 表按 "學(xué)生姓名" 列進(jìn)行分組(注:這一步開(kāi)始才可以使用select中的別名,他返回的是一個(gè)游標(biāo),而不是一個(gè)表,所以在where中不可以使用select中的別名,而having卻可以使用,感謝網(wǎng)友 zyt1369 提出這個(gè)問(wèn)題)

(4). 計(jì)算 max() 聚集函數(shù), 按 "總成績(jī)" 求出總成績(jī)中最大的一些數(shù)值

(5). 執(zhí)行 HAVING 子句, 篩選課程的總成績(jī)大于 600 分的.

(7). 執(zhí)行 ORDER BY 子句, 把最后的結(jié)果按 "Max 成績(jī)" 進(jìn)行排序.

各種Join的語(yǔ)句和圖

我在網(wǎng)上看到的這個(gè),對(duì)于理解join操作很棒。整個(gè)搬過(guò)來(lái),以后在這里方便查看。

這個(gè)是原始表:

id name       id  name
-- ----       --  ----
1  Pirate     1   Rutabaga
2  Monkey     2   Pirate
3  Ninja      3   Darth Vader
4  Spaghetti  4   Ninja

inner join
內(nèi)聯(lián)
SELECT * FROM TableA
INNER JOIN TableB
ON TableA.name = TableB.name
 
id  name       id   name
--  ----       --   ----
1   Pirate     2    Pirate
3   Ninja      4    Ninja

內(nèi)聯(lián)合(inner join)只生成同時(shí)匹配表A和表B的記錄集

full outer join
全外聯(lián)合
SELECT * FROM TableA
FULL OUTER JOIN TableB
ON TableA.name = TableB.name
 
id    name       id    name
--    ----       --    ----
1     Pirate     2     Pirate
2     Monkey     null  null
3     Ninja      4     Ninja
4     Spaghetti  null  null
null  null       1     Rutabaga       
null  null       3     Darth Vader

全外聯(lián)合(full outer join)生成表A和表B里的記錄全集,包括兩邊都匹配的記錄。如果有一邊沒(méi)有匹配的,缺失的這一邊為null。并且我們看到,以TableA為基準(zhǔn)表,然后表B來(lái)匹配,當(dāng)表A中沒(méi)有表B中的元素時(shí),表B中元素排列的順序也是按照id大小。先保證基準(zhǔn)表全部輸出,然后再去看A中沒(méi)有B有的。

left outer join
左外聯(lián)合
SELECT * FROM TableA
LEFT OUTER JOIN TableB
ON TableA.name = TableB.name
 
id  name       id    name
--  ----       --    ----
1   Pirate     2     Pirate
2   Monkey     null  null
3   Ninja      4     Ninja
4   Spaghetti  null  null

左外聯(lián)合(left outer join)生成表A的所有記錄,包括在表B里匹配的記錄。如果沒(méi)有匹配的,右邊將是null

那right join就和這個(gè)一樣了,只是相反而已

下面看看其他幾種集合的表現(xiàn)形式:

只取表A中有,但表B中沒(méi)有的

為了生成只在表A里而不在表B里的記錄集,我們用同樣的左外聯(lián)合,然后用where語(yǔ)句排除我們不想要的記錄

SELECT * FROM TableA
LEFT OUTER JOIN TableB
ON TableA.name = TableB.name
WHERE TableB.id IS null
 
id  name       id     name
--  ----       --     ----
2   Monkey     null   null
4   Spaghetti  null   null

只取表A中和表B中各自有的

為了生成對(duì)于表A和表B唯一的記錄集,我們用同樣的全外聯(lián)合,然后用where語(yǔ)句排除兩邊都不想要的記錄


SELECT * FROM TableA
FULL OUTER JOIN TableB
ON TableA.name = TableB.name
WHERE TableA.id IS null 
OR TableB.id IS null
 
id    name       id    name
--    ----       --    ----
2     Monkey     null  null
4     Spaghetti  null  null
null  null       1     Rutabaga
null  null       3     Darth Vader

全家福:

image.png

參考文章:
畫(huà)圖解釋 SQL join 語(yǔ)句
MySQL explain執(zhí)行計(jì)劃解讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是數(shù)據(jù)庫(kù)? 數(shù)據(jù)庫(kù)是存儲(chǔ)數(shù)據(jù)的集合的單獨(dú)的應(yīng)用程序。每個(gè)數(shù)據(jù)庫(kù)具有一個(gè)或多個(gè)不同的API,用于創(chuàng)建,訪問(wèn),管理...
    chen_000閱讀 4,148評(píng)論 0 19
  • MySQL技術(shù)內(nèi)幕:SQL編程 姜承堯 第1章 SQL編程 >> B是由MySQL創(chuàng)始人之一Monty分支的一個(gè)版...
    沉默劍士閱讀 2,649評(píng)論 0 3
  • SQL SELECT 語(yǔ)句 一、查詢SQL SELECT 語(yǔ)法 (1)SELECT 列名稱 FROM 表名稱 (2...
    有錢(qián)且幸福閱讀 6,011評(píng)論 0 33
  • 系統(tǒng)層面(基本不用動(dòng),看了下,買(mǎi)的云服務(wù)器基本都已經(jīng)優(yōu)化過(guò)了) 內(nèi)核相關(guān)參數(shù)(/etc/sysctl.conf) ...
    神奇大葉子閱讀 2,145評(píng)論 0 4
  • 回歸簡(jiǎn)書(shū)有幾天了,還在適應(yīng)簡(jiǎn)書(shū)的變化中。昨天看了幾篇文章,包括韓大爺?shù)奈恼隆段医ㄗh你去讀一讀那些閱讀量不高的文章》...
    d5f3ae813a4e閱讀 596評(píng)論 47 11

友情鏈接更多精彩內(nèi)容