MySQL調優系列基礎篇

來源:互聯網
上載者:User

標籤:

前言

有一段時間沒有寫部落格了,整天都在忙,上班,錄製課程,恰巧最近一段時間比較清閑,打算弄弄MYSQL資料庫。

關於MySQL資料庫,這裡就不做過多的介紹,開源、免費等特性深受各個互連網行業喜愛,尤其在某些大型電商應用之後,更是將其推崇至極。

前面有一段時間我寫過SQL Server資料庫的一個調優系列,有興趣的可以關注下。

從本篇起,我將開始分析關於MySQL資料庫的一系列的調優內容,同樣作為開篇,先就在MySQL調優中所最常用的查詢計劃進行解析,力圖做好基礎的掌握,夯實基本功!而後再談談整體的語句調優。

文章的部分內容會將MySQL資料庫和SQL Server資料庫部分內容做一個對比,非抨擊孰優孰劣,只敘述技術,權做學習之用。

技術準備

宿主於Window平台下,基於MYSQL5.6版本,利用內建的案例庫(sakila)進行解析。 

一、關於查詢計劃

其實,關於所有的關係型資料庫中,在運行T-SQL語句的時候,在查詢器進行編譯啟動並執行同時,都會有著自己的內部的一個最佳化過程,而這最佳化之後的產物就是:執行計畫。

在SQL SERVER中,我們可以通過很多方式進行查看,方便與對查詢語句的執行過程有一定的掌握,同樣在MYSQL中,也有著自己的執行計畫,相對於SQL Server,它的執行計畫的查看方式如下:

EXPLAIN [EXTENDED] SELECT select_options 

其實,很簡單的一個查看方式,只需要將我們要關心最佳化的語句前面加上:EXPLAN關鍵字,MYSQL就會為我們評估當前語句要執行時需要關注的一些點。

類似於SQL SERVER的執行計畫,但是可能沒有SQL SERVER詳細和直觀,但是這不妨礙對語句的調優。

來個簡單的例子: 

EXPLAIN select * from sakila.film_actor where film_id= 1

 

簡單的來分析下,上面輸出表的內容項。

select_type:SELECT類型

<1>SIMPLE:簡單的select(不適用UNION或子查詢)

<2>PRIMARY:最外面的select

<3>UNION:UNION中的第二個或後面的SELECT語句

<4>DEPENDENT UNION:UNION中的第二個或後面的select語句,取決於外面的查詢

<5>UNION RESUT:UNOION的結果

<6>SUBQUERY:子查詢中的第一個SELECT

<7>DEPENDENT SUBQUERY:子查詢中的第一個SELECT,取決於外面的查詢

<8>DERIVED:匯出表的SELECT(FROM子句的子查詢)

 

table:查詢的表名

type:連線類型

這裡是影響查詢效率的一個很關鍵的參考項,其中包含以下內容值,效能的好壞依次為:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

越靠前的訪問類型,效率越高,速度越快,也是我們要最佳化的目標項。

一般來說,得保證查詢至少達到range層級,最好能到REF,而最爛的就是最後一個ALL....這個在SQL SERVER中就類似於SCALE....全表掃描...

下面,我們依次來分析下這幾個連線類型的應用情境:

<1>system:表僅有一行(=系統資料表)。這個一般是一個變數值,是const連線類型的一個特例。

<2>const:表最多的一個匹配行,它將查詢開始被讀取。因為僅有一行,在這行的列值可被最佳化器的剩餘部分認為是常數。const用於用常數值比較primary key或unique索引的所有部分時。

<3>eq_ref:對於每個來自於前面的表的行組合,從該表中讀取一行。這可能是最好的聯結類型,除了const類型。它用在一個索引的所有部分被聯結使用並且索引是UNIQUE或PRIMARY
KEY。eq_ref可以用於使用= 操作符比較的帶索引的列。比較值可以為常量或一個使用在該表前面所讀取的表的列的運算式。

<4>ref:對於每個來自於前面的表的行組合,所有有匹配索引值的行將從這張表中讀取。如果聯結只使用鍵的最左邊的首碼,或如果鍵不是UNIQUE或PRIMARY KEY(換句話說,如果聯結不能基於關鍵字選擇單個行的話),則使用ref。如果使用的鍵僅僅匹配少量行,該聯結類型是不錯的。ref可以用於使用=或<=>操作符的帶索引的列。

<5>ref_or_null:該聯結類型如同ref,但是添加了MySQL可以專門搜尋包含NULL值的行。在解決子查詢中經常使用該聯結類型的最佳化。

<6>index_merge:該聯結類型表示使用了索引合并最佳化方法。在這種情況下,key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關鍵元素。

<7>unique_subquery:該類型替換了下面形式的IN子查詢的ref:value IN (SELECT primary_key FROMsingle_table WHERE some_expr);unique_subquery是一個索引尋找函數,可以完全替換子查詢,效率更高。

<8>index_subquery:該聯結類型類似於unique_subquery。可以替換IN子查詢,但只適合下列形式的子查詢中的非唯一索引:value IN SELECT key_column FROM single_table WHERE some_expr)

<9>range:只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪個索引。key_len包含所使用索引的最長關鍵元素。在該類型中ref列為NULL。當使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比較關鍵字列時,可以使用range

<10>index:該聯結類型與ALL相同,除了只有索引樹被掃描。這通常比ALL快,因為索引檔案通常比資料檔案小。

<11>all:對於每個來自於先前的表的行組合,進行完整的表掃描。如果表是第一個沒標記const的表,這通常不好,並且通常在它情況下很差。通常可以增加更多的索引而不要使用ALL,使得行能基於前面的表中的常數值或列值被檢索出。

 

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將實際使用一個多部關鍵字的幾個部分。

ref:ref列顯示使用哪個列或常數與key一起從表中選擇行。

rows:rows列顯示MySQL認為它執行查詢時必須檢查的行數。

 

Extra:該列包含MySQL解決查詢的詳細資料。

<1>Distinct:MySQL發現第1個匹配行後,停止為當前的行組合搜尋更多的行。

<2>Not exists:MySQL能夠對查詢進行LEFT JOIN最佳化,發現1個匹配LEFT JOIN標準的行後,不再為前面的的行組合在該表內檢查更多的行。

<3>range checked for each record (index map: #):MySQL沒有發現好的可以使用的索引,但發現如果來自前面的表的列值已知,可能部分索引可以使用。對前面的表的每個行組合,MySQL檢查是否可以使用range或index_merge存取方法來索取行。

<4>Using filesort:MySQL需要額外的一次傳遞,以找出如何按排序次序檢索行。通過根據聯結類型瀏覽所有行並為所有匹配WHERE子句的行儲存排序關鍵字和行的指標來完成排序。然後關鍵字被排序,並按排序次序檢索行。

<5>Using index:從只使用索引樹中的資訊而不需要進一步搜尋讀取實際的行來檢索表中的列資訊。當查詢只使用作為單一索引一部分的列時,可以使用該策略。

<6>Using temporary:為瞭解決查詢,MySQL需要建立一個暫存資料表來容納結果。典型情況如查詢包含可以按不同情況列出列的GROUP BY和ORDER BY子句時。

<7>Using where:WHERE子句用於限制哪一個行匹配下一個表或發送到客戶。除非你專門從表中索取或檢查所有行,如果Extra值不為Using where並且表聯結類型為ALL或index,查詢可能會有一些錯誤。

<8>Using sort_union(...), Using union(...), Using intersect(...):這些函數說明如何為index_merge聯結類型合并索引掃描。

<9>Using index for group-by:類似於訪問表的Using index方式,Using index for group-by表示MySQL發現了一個索引,可以用來查詢GROUP BY或DISTINCT查詢的所有列,而不要額外搜尋硬碟訪問實際的表。並且,按最有效方式使用索引,以便對於每個組,唯讀取少量索引條目。

 

我們知道,在資料量達到一定的程度之後,如果僅僅通過簡單的表掃描來擷取資料,那將是一個很好資源並且效能很爛的執行過程,而這過程當中一般的調優方案就是通過添加索引的方式進行,下面來一個簡單的例子說明:

use test;#建立表create table testOneRow(A int,b varchar(5));#插入資料insert into testOneRow values(1,‘111‘)

我們簡單的來執行一個指令碼

explain select b from testOneRow

這裡可以看到,只是單純的通過表掃描(ALL)來擷取資料,沒有任何索引來最佳化查詢。

下面我們來建立一個索引

CREATE INDEX index_b ON testOneRow (b)

大家,可以看到,這就是一個簡單通過建立索引來最佳化T-SQL的例子。

 

結語

此篇文章先到此吧,關於MYSQL效能調優的內容涉及面很廣,後續文章中依次展開分析。

 

如果您看了本篇部落格,覺得對您有所收穫,請不要吝嗇您的“推薦”。

MySQL調優系列基礎篇

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.