??博主介紹??:
?又是一天沒白過,我是奈斯,DBA一名?
???擅長Oracle、MySQL、SQLserver、Linux,也在積極的擴展IT方向的其他知識面???
??????大佬們都喜歡靜靜的看文章,并且也會默默的點贊收藏加關注??????
? ? 士別三日,自上次分享以來,大家應該對上篇的文章內容進行了深入消化與理解。今天給大家帶來第二篇的內容——執行計劃。在上篇文章中我們有了解到optimizer優化器根據統計信息對每個sql語句執行最優的執行計劃(執行計劃受統計信息影響)。并且通過執行計劃能夠幫助我們了解數據庫在執行查詢時采用的具體策略、使用的索引以及各種操作的執行順序等信息,因此對于SQL查詢的優化非常重要。
? ? 因為統計信息和執行計劃涉及到的內容過多,為了使大家更好消化,我將分成三篇文章來進行介紹,以便大家因為篇幅過長而感到閱讀疲憊。三篇的內容分別如下,讓大家先做了解:
第一篇:持久化和非持久化統計信息介紹
第二篇:執行計劃介紹(當前篇)
第三篇:執行計劃之覆蓋索引Using index和條件過濾Using where詳細介紹
目錄
查看SQL的執行計劃
explain語法一:explain + SQL語句(默認FORMAT = TRADITIONAL輸出格式為表格)
explain語法二:explain FORMAT = JSON + SQL語句
explain語法三:explain FORMAT = TREE + SQL語句
explain語法四:explain analyze + SQL語句
廢話不多說,讓我們開始今天的內容。
? ??MySQL中的SQL執行計劃能夠幫助我們了解數據庫在執行查詢時采用的具體策略、使用的索引以及各種操作的執行順序等信息,因此對于SQL查詢的優化非常重要。下面是SQL執行計劃在SQL查詢優化中的作用:
1)評估查詢性能:SQL 執行計劃可以讓我們了解到 MySQL 在執行查詢時所采用的具體策略和每個步驟所需的時間,從而評估查詢的性能表現。比如,我們可以查看每個操作使用的索引類型或臨時表的創建情況,有助于我們確定查詢是否需要進行優化,以及應該優化哪些部分。
2)定位性能問題:如果SQL查詢執行緩慢,我們可以通過 SQL 執行計劃來定位性能問題所在。例如,我們可以查看查詢語句中是否存在不必要的排序、全表掃描、臨時表創建等問題,從而確定性能瓶頸并進行調整。
3)判斷索引是否有效:SQL 執行計劃可以讓我們了解到 MySQL 是否使用了正確的索引來執行查詢,進而判斷我們為表設置的索引是否有效。如果 MySQL 沒有使用索引,那么可能是我們設置的索引有問題,需要重新考慮索引的創建方式。
4)選擇正確的查詢方案:在SQL查詢優化中,有時候我們需要選擇不同的查詢方案來完成同樣的查詢操作。SQL 執行計劃可以讓我們了解到MySQL計劃使用哪種查詢方案,并可以根據不同的情況調整查詢方案或者SQL語句結構。
總之,SQL 執行計劃是 SQL 查詢優化的重要工具,可以幫助我們找到問題所在,優化查詢性能并提高數據庫的運行效率。
? ? ? ? ? ? ??
查看SQL的執行計劃
? ? 通過explain查看執行計劃的方式有多種,今天主要是詳細介紹語法一,其他的方式我這里不多做介紹,因為都是大同小異,有興趣的小伙伴可以私信我。
EXPLAIN語法:
官方文檔對EXPLAIN的介紹:MySQL :: MySQL 8.0 Reference Manual :: 15.8.2 EXPLAIN Statement
{EXPLAIN | DESCRIBE | DESC}
????tbl_name [col_name | wild]
{EXPLAIN | DESCRIBE | DESC}
????[explain_type]
????{explainable_stmt | FOR CONNECTION connection_id}
{EXPLAIN | DESCRIBE | DESC} ANALYZE [FORMAT = TREE] select_statement
explain_type: {
????FORMAT = format_name
}
format_name: {
??| TRADITIONAL
??| JSON
??| TREE
}
explainable_stmt: {
??| SELECT statement
??| TABLE statement
??| DELETE statement
??| INSERT statement
??| REPLACE statement
??| UPDATE statement
}
EXPLAIN [options]?FOR CONNECTION connection_id:獲取在命名連接中執行的可解釋語句的執行計劃。意思就是在另一個會話上去查看其他會話正在執行SQL的執行計劃,通常的做法是在另一個會話上輸入show porcesslist(或者其他查詢SQL的語句),有正在執行的SQL那么通過EXPLAIN [options]?FOR CONNECTION加上show processlist輸出的ID,那么可以看到相關SQL的執行計劃。
FORMAT = format_name:選項可用于選擇輸出格式。默認以表格格式顯示輸出(FORMAT = TRADITIONAL)。可以指定其他輸出格式,JSON格式以JSON格式顯示信息(FORMAT = JSON)。在MySQL 8.0.16及更高版本中,TREE提供了樹狀輸出(FORMAT = TREE),比傳統格式更精確地描述了查詢處理,并且它是唯一顯示哈希連接用法的格式,和EXPLAIN ANALYZE輸出的內容大致相同。在MySQL 8.0.32中添加的explain_format系統變量在用于獲取表列信息時,影響對explain的輸出,參數的值包括TRADITIONAL (DEFAULT)、JSON、TREE。
explainable_stmt:EXPLAIN適用于SELECT、DELETE、INSERT、REPLACE和UPDATE語句的執行計劃的解析。在MySQL 8.0.19及更高版本中,它還可以使用TABLE語句,TABLE語句是MySQL 8.0.19中引入的DML語句,它返回指定表的行和列,和SELECT查詢表有些類似,但功能又沒SELECT多。
注意:SQL語句加上explain不會真正執行SQL語句,它僅會模擬MySQL在執行該語句時所做的操作,并返回MySQL在執行該語句時使用的查詢計劃信息。
? ? ? ? ? ??
explain語法一:explain + SQL語句(默認FORMAT = TRADITIONAL輸出格式為表格)
mysql> explain select * from tb t1 join tb2 t2 on t1.id=t2.id;
需要特別關注的字段type、possible_keys、key、key_len、ref、rows、Extra。官方文檔解釋輸出列:MySQL :: MySQL 8.0 Reference Manual :: 10.8.2 EXPLAIN Output Format
id(JSON名稱:select_id):SELECT標識符。這是查詢中SELECT的序列號。如果該行引用其他行的并集結果,則該值可以為NULL。在這種情況下,表列顯示一個類似于<union M,N>的值,表示該行指的是id值為M和N的行的并集。
select_type(JSON名稱:無):SELECT的類型。JSON格式的EXPLAIN將SELECT類型公開為query_block的屬性,除非它是SIMPLE或PRIMARY。類型比較多,參考官方文檔。
table(JSON名稱:table_name):輸出行所引用的表的名稱。
partitions(JSON名稱:partitions):查詢將從中匹配記錄的分區。對于未分區的表該值為NULL。
type(JSON名稱:access_type):聯接類型。類型比較多,參考官方文檔。
possible_keys(JSON名稱:possible_ keys):possible_keys列表示MySQL可以從中選擇查找該表中的行的索引。請注意,此列完全獨立于EXPLAIN輸出中顯示的表的順序。這意味著possible_keys中的一些鍵在實際中可能無法使用生成的表順序。如果此列為NULL(或在JSON格式的輸出中未定義),則不存在相關索引。在這種情況下,您可以通過檢查WHERE子句來檢查它是否引用了適合進行索引的一個或多個列,從而提高查詢的性能。如果是,請創建一個適當的索引ALTER TABLE語句,并再次使用EXPLAIN檢查查詢。要查看表的索引,請使用SHOW INDEX FROM tbl_name。
key(JSON名稱:key):這key列表示MySQL實際決定使用的鍵(索引)。如果MySQL決定使用possible_keys索引來查找行,該索引被列為鍵值。有可能key可以命名一個不在possible_keys價值。如果沒有一個possible_keys索引適合于查找行,但是查詢選擇的所有列都是其他索引的列。也就是說,命名索引覆蓋了所選的列,因此盡管它不用于確定要檢索哪些行,但索引掃描比數據行掃描更有效。
為InnoDB,即使查詢也選擇了主鍵,輔助索引也可能會覆蓋選定的列,因為InnoDB存儲每個輔助索引的主鍵值。如果key是NULL,MySQL找不到索引來更有效地執行查詢。要強制MySQL使用或忽略possible_keys列,使用FORCE INDEX, USE INDEX,或者IGNORE INDEX在您的查詢中。看見第8.9.4節,“索引提示”.
為MyISAM表格,運行ANALYZE TABLE幫助優化器選擇更好的索引。為MyISAM表格,myisamchk -分析做同樣的事。看見13.7.3.1,“分析表語句”一節,以及第7.6節,“MyISAM表維護和故障恢復”.
key_len(JSON名稱:key_length):key_len列表示MySQL決定使用的密鑰的長度。key_len的值使您能夠確定MySQL實際使用多部分密鑰的多少部分。如果key列表示NULL,那么key_len列也表示NULL。由于密鑰存儲格式的原因,可以為NULL的列的密鑰長度比NOT NULL列的密鑰長一個。
ref(JSON名稱:ref):ref列顯示將哪些列或常量與鍵列中命名的索引進行比較,以便從表中選擇行。如果該值是func,則使用的值是某個函數的結果。要查看哪個函數,請在EXPLAIN后面使用SHOW WARNINGS來查看擴展的EXPLAIN輸出。函數實際上可能是一個運算符,例如算術運算符。
rows(JSON名稱:rows):rows列表示MySQL認為執行查詢必須檢查的行數。這里的行數和自動更新持久化統計信息是一致的,所以會出現與實際count(*)數據量差距較大,可以這個文檔的2、統計信息的案例“(6)解決統計信息差別較大的問題(執行計劃受統計信息影響,統計信息不準會導致執行計劃不準)”
filtered(JSON名稱:filtered):已篩選列表示按表條件篩選的表行的估計百分比。最大值為100,這意味著沒有對行進行篩選。從100開始遞減的值表示過濾量的增加。rows顯示檢查的估計行數,rows×filtered顯示與下表連接的行數。例如,如果行數為1000,過濾后的行數為50.00(50%),則與下表連接的行數是1000×50%=500。
Extra(JSON名稱:無):本列包含有關MySQL如何解析查詢的其他信息。沒有一個JSON屬性對應于Extra列;但是,此列中可能出現的值將作為JSON屬性或消息屬性的文本公開。類型比較多,參考官方文檔。
? ? ? ? ? ? ? ? ??
explain語法二:explain FORMAT = JSON + SQL語句
mysql> explain FORMAT = JSON select * from tb t1 join tb2 t2 on t1.id=t2.id\G;
? ? ? ? ? ??
explain語法三:explain FORMAT = TREE + SQL語句
mysql> explain FORMAT = TREE select * from tb t1 join tb2 t2 on t1.id=t2.id\G;
? ? ? ? ? ? ? ?
explain語法四:explain analyze + SQL語句
mysql> explain analyze select * from tb t1 join tb2 t2 on t1.id=t2.id\G;
? ? 今天執行計劃的內容就介紹到這里,只是對執行計劃輸出的內容做了介紹,下一篇我會用實例執行的執行計劃的案例來介紹。