MySQL调优系列基础篇
前言
有一段時間沒有寫博客了,整天都在忙,上班,錄制課程,恰巧最近一段時間比較清閑,打算弄弄MYSQL數(shù)據(jù)庫。
關(guān)于MySQL數(shù)據(jù)庫,這里就不做過多的介紹,開源、免費等特性深受各個互聯(lián)網(wǎng)行業(yè)喜愛,尤其在某些大型電商應(yīng)用之后,更是將其推崇至極。
前面有一段時間我寫過SQL Server數(shù)據(jù)庫的一個調(diào)優(yōu)系列,有興趣的可以關(guān)注下。
從本篇起,我將開始分析關(guān)于MySQL數(shù)據(jù)庫的一系列的調(diào)優(yōu)內(nèi)容,同樣作為開篇,先就在MySQL調(diào)優(yōu)中所最常用的查詢計劃進行解析,力圖做好基礎(chǔ)的掌握,夯實基本功!而后再談?wù)務(wù)w的語句調(diào)優(yōu)。
文章的部分內(nèi)容會將MySQL數(shù)據(jù)庫和SQL Server數(shù)據(jù)庫部分內(nèi)容做一個對比,非抨擊孰優(yōu)孰劣,只敘述技術(shù),權(quán)做學(xué)習(xí)之用。
技術(shù)準備
宿主于Window平臺下,基于MYSQL5.6版本,利用自帶的案例庫(sakila)進行解析。?
一、關(guān)于查詢計劃
其實,關(guān)于所有的關(guān)系型數(shù)據(jù)庫中,在運行T-SQL語句的時候,在查詢器進行編譯運行的同時,都會有著自己的內(nèi)部的一個優(yōu)化過程,而這優(yōu)化之后的產(chǎn)物就是:執(zhí)行計劃。
在SQL SERVER中,我們可以通過很多方式進行查看,方便與對查詢語句的執(zhí)行過程有一定的掌握,同樣在MYSQL中,也有著自己的執(zhí)行計劃,相對于SQL Server,它的執(zhí)行計劃的查看方式如下:
EXPLAIN [EXTENDED] SELECT select_options其實,很簡單的一個查看方式,只需要將我們要關(guān)心優(yōu)化的語句前面加上:EXPLAN關(guān)鍵字,MYSQL就會為我們評估當前語句要執(zhí)行時需要關(guān)注的一些點。
類似于SQL SERVER的執(zhí)行計劃,但是可能沒有SQL SERVER詳細和直觀,但是這不妨礙對語句的調(diào)優(yōu)。
來個簡單的例子:?
EXPLAIN select * from sakila.film_actor where film_id= 1?
簡單的來分析下,上面輸出表的內(nèi)容項。
select_type:SELECT類型
<1>SIMPLE:簡單的select(不適用UNION或子查詢)
<2>PRIMARY:最外面的select
<3>UNION:UNION中的第二個或后面的SELECT語句
<4>DEPENDENT UNION:UNION中的第二個或后面的select語句,取決于外面的查詢
<5>UNION RESUT:UNOION的結(jié)果
<6>SUBQUERY:子查詢中的第一個SELECT
<7>DEPENDENT SUBQUERY:子查詢中的第一個SELECT,取決于外面的查詢
<8>DERIVED:導(dǎo)出表的SELECT(FROM子句的子查詢)
?
table:查詢的表名
type:連接類型
這里是影響查詢效率的一個很關(guān)鍵的參考項,其中包含以下內(nèi)容值,性能的好壞依次為:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
越靠前的訪問類型,效率越高,速度越快,也是我們要優(yōu)化的目標項。
一般來說,得保證查詢至少達到range級別,最好能到REF,而最爛的就是最后一個ALL....這個在SQL SERVER中就類似于SCALE....全表掃描...
下面,我們依次來分析下這幾個連接類型的應(yīng)用場景:
<1>system:表僅有一行(=系統(tǒng)表)。這個一般是一個變量值,是const連接類型的一個特例。
<2>const:表最多的一個匹配行,它將查詢開始被讀取。因為僅有一行,在這行的列值可被優(yōu)化器的剩余部分認為是常數(shù)。const用于用常數(shù)值比較primary key或unique索引的所有部分時。
<3>eq_ref:對于每個來自于前面的表的行組合,從該表中讀取一行。這可能是最好的聯(lián)接類型,除了const類型。它用在一個索引的所有部分被聯(lián)接使用并且索引是UNIQUE或PRIMARY
KEY。eq_ref可以用于使用=?操作符比較的帶索引的列。比較值可以為常量或一個使用在該表前面所讀取的表的列的表達式。
<4>ref:對于每個來自于前面的表的行組合,所有有匹配索引值的行將從這張表中讀取。如果聯(lián)接只使用鍵的最左邊的前綴,或如果鍵不是UNIQUE或PRIMARY KEY(換句話說,如果聯(lián)接不能基于關(guān)鍵字選擇單個行的話),則使用ref。如果使用的鍵僅僅匹配少量行,該聯(lián)接類型是不錯的。ref可以用于使用=或<=>操作符的帶索引的列。
<5>ref_or_null:該聯(lián)接類型如同ref,但是添加了MySQL可以專門搜索包含NULL值的行。在解決子查詢中經(jīng)常使用該聯(lián)接類型的優(yōu)化。
<6>index_merge:該聯(lián)接類型表示使用了索引合并優(yōu)化方法。在這種情況下,key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關(guān)鍵元素。
<7>unique_subquery:該類型替換了下面形式的IN子查詢的ref:value?IN (SELECT?primary_key?FROMsingle_table?WHERE?some_expr);unique_subquery是一個索引查找函數(shù),可以完全替換子查詢,效率更高。
<8>index_subquery:該聯(lián)接類型類似于unique_subquery。可以替換IN子查詢,但只適合下列形式的子查詢中的非唯一索引:value?IN SELECT?key_column?FROM?single_table?WHERE?some_expr)
<9>range:只檢索給定范圍的行,使用一個索引來選擇行。key列顯示使用了哪個索引。key_len包含所使用索引的最長關(guān)鍵元素。在該類型中ref列為NULL。當使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比較關(guān)鍵字列時,可以使用range
<10>index:該聯(lián)接類型與ALL相同,除了只有索引樹被掃描。這通常比ALL快,因為索引文件通常比數(shù)據(jù)文件小。
<11>all:對于每個來自于先前的表的行組合,進行完整的表掃描。如果表是第一個沒標記const的表,這通常不好,并且通常在它情況下很差。通??梢栽黾痈嗟乃饕灰褂肁LL,使得行能基于前面的表中的常數(shù)值或列值被檢索出。
?
possible_keys:指出MySQL能使用哪個索引在該表中找到行。注意,該列完全獨立于EXPLAIN輸出所示的表的次序。這意味著在possible_keys中的某些鍵實際上不能按生成的表次序使用。
key:key列顯示MySQL實際決定使用的鍵(索引)。如果沒有選擇索引,鍵是NULL。要想強制MySQL使用或忽視possible_keys列中的索引,在查詢中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。
key_len:key_len列顯示MySQL決定使用的鍵長度。如果鍵是NULL,則長度為NULL。注意通過key_len值我們可以確定MySQL將實際使用一個多部關(guān)鍵字的幾個部分。
ref:ref列顯示使用哪個列或常數(shù)與key一起從表中選擇行。
rows:rows列顯示MySQL認為它執(zhí)行查詢時必須檢查的行數(shù)。
?
Extra:該列包含MySQL解決查詢的詳細信息。
<1>Distinct:MySQL發(fā)現(xiàn)第1個匹配行后,停止為當前的行組合搜索更多的行。
<2>Not exists:MySQL能夠?qū)Σ樵冞M行LEFT JOIN優(yōu)化,發(fā)現(xiàn)1個匹配LEFT JOIN標準的行后,不再為前面的的行組合在該表內(nèi)檢查更多的行。
<3>range checked for each record (index map:?#):MySQL沒有發(fā)現(xiàn)好的可以使用的索引,但發(fā)現(xiàn)如果來自前面的表的列值已知,可能部分索引可以使用。對前面的表的每個行組合,MySQL檢查是否可以使用range或index_merge訪問方法來索取行。
<4>Using filesort:MySQL需要額外的一次傳遞,以找出如何按排序順序檢索行。通過根據(jù)聯(lián)接類型瀏覽所有行并為所有匹配WHERE子句的行保存排序關(guān)鍵字和行的指針來完成排序。然后關(guān)鍵字被排序,并按排序順序檢索行。
<5>Using index:從只使用索引樹中的信息而不需要進一步搜索讀取實際的行來檢索表中的列信息。當查詢只使用作為單一索引一部分的列時,可以使用該策略。
<6>Using temporary:為了解決查詢,MySQL需要創(chuàng)建一個臨時表來容納結(jié)果。典型情況如查詢包含可以按不同情況列出列的GROUP BY和ORDER BY子句時。
<7>Using where:WHERE子句用于限制哪一個行匹配下一個表或發(fā)送到客戶。除非你專門從表中索取或檢查所有行,如果Extra值不為Using where并且表聯(lián)接類型為ALL或index,查詢可能會有一些錯誤。
<8>Using sort_union(...),?Using union(...),?Using intersect(...):這些函數(shù)說明如何為index_merge聯(lián)接類型合并索引掃描。
<9>Using index for group-by:類似于訪問表的Using index方式,Using index for group-by表示MySQL發(fā)現(xiàn)了一個索引,可以用來查詢GROUP BY或DISTINCT查詢的所有列,而不要額外搜索硬盤訪問實際的表。并且,按最有效的方式使用索引,以便對于每個組,只讀取少量索引條目。
?
我們知道,在數(shù)據(jù)量達到一定的程度之后,如果僅僅通過簡單的表掃描來獲取數(shù)據(jù),那將是一個很好資源并且性能很爛的執(zhí)行過程,而這過程當中一般的調(diào)優(yōu)方案就是通過添加索引的方式進行,下面來一個簡單的例子說明:
use test; #創(chuàng)建表 create table testOneRow(A int,b varchar(5)); #插入數(shù)據(jù) insert into testOneRow values(1,'111')我們簡單的來執(zhí)行一個腳本
explain select b from testOneRow這里可以看到,只是單純的通過表掃描(ALL)來獲取數(shù)據(jù),沒有任何索引來優(yōu)化查詢。
下面我們來創(chuàng)建一個索引
CREATE INDEX index_b ON testOneRow (b)大家,可以看到,這就是一個簡單通過創(chuàng)建索引來優(yōu)化T-SQL的例子。
?
結(jié)語
此篇文章先到此吧,關(guān)于MYSQL性能調(diào)優(yōu)的內(nèi)容涉及面很廣,后續(xù)文章中依次展開分析。
?
如果您看了本篇博客,覺得對您有所收獲,請不要吝嗇您的“推薦”。
轉(zhuǎn)載于:https://www.cnblogs.com/zhijianliutang/p/4731307.html
總結(jié)
以上是生活随笔為你收集整理的MySQL调优系列基础篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在页面上显示PDF
- 下一篇: windows mysqldump 不