本文咱們主要介紹了MySQL性能分析以及explain的使用,包括:組合索引、慢查詢分析、MYISAM和INNODB的鎖定、MYSQL的事務配置項等,但願可以對您有所幫助。mysql
1.使用explain語句去查看分析結果
如explain select * from test1 where id=1;會出現:id selecttype table type possible_keys key key_len ref rows extra各列。算法
其中,
type=const表示經過索引一次就找到了;
key=primary的話,表示使用了主鍵;
type=all,表示爲全表掃描;
key=null表示沒用到索引。sql
type=ref,由於這時認爲是多個匹配行,在聯合查詢中,通常爲REF。緩存
MySQL 查詢優化器是如何工做的
MySQL 查詢優化器有幾個目標,可是其中最主要的目標是儘量地使用索引,而且使用最嚴格的索引來消除儘量多的數據行。最終目標是提交 SELECT 語句查找數據行,而不是排除數據行。優化器試圖排除數據行的緣由在於它排除數據行的速度越快,那麼找到與條件匹配的數據行也就越快。若是可以首先進行最嚴格的測試,查詢就能夠執行地更快。
EXPLAIN 的每一個輸出行提供一個表的相關信息,而且每一個行包括下面的列: 安全
項 | 說明 |
id | MySQL Query Optimizer 選定的執行計劃中查詢的序列號。表示查詢中執行 select 子句或操做表的順序,id 值越大優先級越高,越先被執行。id 相同,執行順序由上至下。 |
select_type 查詢類型 | 說明 |
SIMPLE | 簡單的 select 查詢,不使用 union 及子查詢 |
PRIMARY | 最外層的 select 查詢 |
UNION | UNION 中的第二個或隨後的 select 查詢,不 依賴於外部查詢的結果集 |
DEPENDENT UNION | UNION 中的第二個或隨後的 select 查詢,依 賴於外部查詢的結果集 |
SUBQUERY | 子查詢中的第一個 select 查詢,不依賴於外 部查詢的結果集 |
DEPENDENT SUBQUERY | 子查詢中的第一個 select 查詢,依賴於外部 查詢的結果集 |
DERIVED | 用於 from 子句裏有子查詢的狀況。 MySQL 會 遞歸執行這些子查詢, 把結果放在臨時表裏。 |
UNCACHEABLE SUBQUERY | 結果集不能被緩存的子查詢,必須從新爲外 層查詢的每一行進行評估。 |
UNCACHEABLE UNION | UNION 中的第二個或隨後的 select 查詢,屬 於不可緩存的子查詢 |
項 | 說明 |
table | 輸出行所引用的表 |
type 重要的項,顯示鏈接使用的類型,按最 優到最差的類型排序 | 說明 |
system | 表僅有一行(=系統表)。這是 const 鏈接類型的一個特例。 |
const | const 用於用常數值比較 PRIMARY KEY 時。當 查詢的表僅有一行時,使用 System。 |
eq_ref | const 用於用常數值比較 PRIMARY KEY 時。當 查詢的表僅有一行時,使用 System。 |
ref | 鏈接不能基於關鍵字選擇單個行,可能查找 到多個符合條件的行。 叫作 ref 是由於索引要 跟某個參考值相比較。這個參考值或者是一 個常數,或者是來自一個表裏的多表查詢的 結果值。 |
ref_or_null | 如同 ref, 可是 MySQL 必須在初次查找的結果 裏找出 null 條目,而後進行二次查找。 |
index_merge | 說明索引合併優化被使用了。 |
unique_subquery | 在某些 IN 查詢中使用此種類型,而不是常規的 ref:value IN (SELECT primary_key FROM single_table WHERE some_expr) |
index_subquery | 在 某 些 IN 查 詢 中 使 用 此 種 類 型 , 與 unique_subquery 相似,可是查詢的是非惟一 性索引: value IN (SELECT key_column FROM single_table WHERE some_expr) |
range | 只檢索給定範圍的行,使用一個索引來選擇 行。key 列顯示使用了哪一個索引。當使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操做符,用常量比較關鍵字列時,可 以使用 range。 |
index | 全表掃描,只是掃描表的時候按照索引次序 進行而不是行。主要優勢就是避免了排序, 可是開銷仍然很是大。 |
all | 最壞的狀況,從頭至尾全表掃描。 |
項 | 說明 |
possible_keys | 指出 MySQL 能在該表中使用哪些索引有助於 查詢。若是爲空,說明沒有可用的索引。 |
項 | 說明 |
key | MySQL 實際從 possible_key 選擇使用的索引。 若是爲 NULL,則沒有使用索引。不多的狀況 下,MYSQL 會選擇優化不足的索引。這種情 況下,能夠在 SELECT 語句中使用 USE INDEX (indexname)來強制使用一個索引或者用 IGNORE INDEX(indexname)來強制 MYSQL 忽略索引 |
項 | 說明 |
key_len | 使用的索引的長度。在不損失精確性的狀況 下,長度越短越好。 |
項 | 說明 |
ref | 顯示索引的哪一列被使用了 |
項 | 說明 |
rows | MYSQL 認爲必須檢查的用來返回請求數據的行數 |
項 | 說明 |
rows | MYSQL 認爲必須檢查的用來返回請求數據的行數 |
extra 中出現如下 2 項意味着 MYSQL 根本不能使用索引,效率會受到重大影響。應儘量對此進行優化。服務器
extra 項 | 說明 |
Using filesort | 表示 MySQL 會對結果使用一個外部索引排序,而不是從表裏按索引次序讀到相關內容。可能在內存或者磁盤上進行排序。MySQL 中沒法利用索引完成的排序操做稱爲「文件排序」 |
Using temporary | 表示 MySQL 在對查詢結果排序時使用臨時表。常見於排序 order by 和分組查詢 group by。 |
2.MYSQL中的組合索引
假設表有id,key1,key2,key3,把三者造成一個組合索引,則如:
複製代碼 代碼以下:函數
根據最左前綴原則,這些都是可使用索引的,如from test where key1=1 order by key3,用explain分析的話,只用到了normal_key索引,但只對where子句起做用,然後面的order by須要排序。性能
3.使用慢查詢分析(實用)
在my.ini中:
long_query_time=1
log-slow-queries=d:\mysql5\logs\mysqlslow.log
把超過1秒的記錄在慢查詢日誌中
能夠用mysqlsla來分析之。也能夠在mysqlreport中,有如
DMS分別分析了select ,update,insert,delete,replace等所佔的百分比測試
4.MYISAM和INNODB的鎖定
myisam中,注意是表鎖來的,好比在多個UPDATE操做後,再SELECT時,會發現SELECT操做被鎖定了,必須等全部UPDATE操做完畢後,再能SELECT
innodb的話則不一樣了,用的是行鎖,不存在上面問題。 優化
5.MYSQL的事務配置項
innodb_flush_log_at_trx_commit=1
表示事務提交時當即把事務日誌flush寫入磁盤,同時數據和索引也更新,很費性能。
innodb_flush_log_at_trx_commit=0
事務提交時,不當即把事務日誌寫入磁盤,每隔1秒寫一次,MySQL掛了可能會丟失事務的數據。
innodb_flush_log_at_trx_commit=2 ,在整個操做系統 掛了時纔可能丟數據,通常不會丟失超過1-2秒的更新。
事務提交時,當即寫入磁盤文件(這裏只是寫入到系統內核緩衝區,但不當即刷新到磁盤,而是每隔1秒刷新到磁盤,同時更新數據和索引),這種方案是否是性價比好一些,固然如何配置,決定於你對系統數據安全性的要求。
explain用法詳解
EXPLAIN tbl_name或:EXPLAIN [EXTENDED] SELECT select_options
前者能夠得出一個表的字段結構等等,後者主要是給出相關的一些索引信息,而今天要講述的重點是後者。
舉例
各個屬性的含義
id :select查詢的序列號
select_type:select查詢的類型,主要是區別普通查詢和聯合查詢、子查詢之類的複雜查詢。
a.SIMPLE:查詢中不包含子查詢或者UNION
b.查詢中若包含任何複雜的子部分,最外層查詢則被標記爲:PRIMARY
c.在SELECT或WHERE列表中包含了子查詢,該子查詢被標記爲:SUBQUERY
d.在FROM列表中包含的子查詢被標記爲:DERIVED(衍生)
e.若第二個SELECT出如今UNION以後,則被標記爲UNION;若UNION包含在 FROM子句的子查詢中,外層SELECT將被標記爲:DERIVED
f.從UNION表獲取結果的SELECT被標記爲:UNION RESULT
table :輸出的行所引用的表。
type :聯合查詢所使用的類型,表示MySQL在表中找到所需行的方式,又稱「訪問類型」。
type顯示的是訪問類型,是較爲重要的一個指標,結果值從好到壞依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL ,通常來講,得保證查詢至少達到range級別,最好能達到ref。
ALL: 掃描全表
index: 掃描所有索引樹
range: 掃描部分索引,索引範圍掃描,對索引的掃描開始於某一點,返回匹配值域的行,常見於between、<、>等的查詢
ref: 非惟一性索引掃描,返回匹配某個單獨值的全部行。常見於使用非惟一索引即惟一索引的非惟一前綴進行的查找
eq_ref:惟一性索引掃描,對於每一個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或惟一索引掃描
const, system: 當MySQL對查詢某部分進行優化,並轉換爲一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換爲一個常量。system是const類型的特例,當查詢的表只有一行的狀況下, 使用system。
NULL: MySQL在優化過程當中分解語句,執行時甚至不用訪問表或索引。
以下所示:
possible_keys:指出MySQL能使用哪一個索引在該表中找到行。查詢涉及到的字段上若存在索引,則該索引將被列出,但不必定被查詢使用。若是是空的,沒有相關的索引。這時要提升性能,可經過檢驗WHERE子句,看是否引用某些字段,或者檢查字段不是適合索引。
key :顯示MySQL實際決定使用的鍵。若是沒有索引被選擇,鍵是NULL。
key_len:顯示MySQL決定使用的鍵長度。表示索引中使用的字節數,可經過該列計算查詢中使用的索引的長度。若是鍵是NULL,長度就是NULL。文檔提示特別注意這個值能夠得出一個多重主鍵裏mysql實際使用了哪一部分。
注:key_len顯示的值爲索引字段的最大可能長度,並不是實際使用長度,即key_len是根據表定義計算而得,不是經過表內檢索出的。
ref:顯示哪一個字段或常數與key一塊兒被使用。
rows:這個數表示mysql要遍歷多少數據才能找到,表示MySQL根據表統計信息及索引選用狀況,估算的找到所需的記錄所須要讀取的行數,在innodb上多是不許確的。
Extra:包含不適合在其餘列中顯示但十分重要的額外信息。
Only index,這意味着信息只用索引樹中的信息檢索出的,這比掃描整個表要快。
using where是使用上了where限制,表示MySQL服務器在存儲引擎受到記錄後進行「後過濾」(Post-filter),若是查詢未能使用索引,Using where的做用只是提醒咱們MySQL將用where子句來過濾結果集。
impossible where 表示用不着where,通常就是沒查出來啥。
Using filesort(MySQL中沒法利用索引完成的排序操做稱爲「文件排序」)當咱們試圖對一個沒有索引的字段進行排序時,就是filesoft。它跟文件沒有任何關係,其實是內部的一個快速排序。
Using temporary(表示MySQL須要使用臨時表來存儲結果集,常見於排序和分組查詢),使用filesort和temporary的話會很吃力,WHERE和ORDER BY的索引常常沒法兼顧,若是按照WHERE來肯定索引,那麼在ORDER BY時,就必然會引發Using filesort,這就要看是先過濾再排序划算,仍是先排序再過濾划算。
最後,再看一個查詢計劃的例子:
第一行:id列爲1,表示第一個select,select_type列的primary表示該查詢爲外層查詢,table列被標記爲<derived3>,表示查詢結果來自一個衍生表,其中3表明該查詢衍生自第三個select查詢,即id爲3的select。[select d1.name......]
第二行:id爲3,表示該查詢的執行次序爲2(4→3),是整個查詢中第三個select的一部分。因查詢包含在from中,因此爲derived。[select id,name from t1 where other_column='']
第三行:select列表中的子查詢,select_type爲subquery,爲整個查詢中的第二個select。[select id from t3]
第四行:select_type爲union,說明第四個select是union裏的第二個select,最早執行。[select name,id from t2]
第五行:表明從union的臨時表中讀取行的階段,table列的<union1,4>表示用第一個和第四個select的結果進行union操做。[兩個結果union操做]
關於MySQL執行計劃的侷限性:
EXPLAIN不會告訴你關於觸發器、存儲過程的信息或用戶自定義函數對查詢的影響狀況
EXPLAIN不考慮各類Cache
EXPLAIN不能顯示MySQL在執行查詢時所做的優化工做
部分統計信息是估算的,並不是精確值
EXPALIN只能解釋SELECT操做,其餘操做要重寫爲SELECT後查看。
備註:
filesort是經過相應的排序算法,將取得的數據在內存中進行排序。
MySQL須要將數據在內存中進行排序,所使用的內存區域也就是咱們經過sort_buffer_size 系統變量所設置的排序區。這個排序區是每一個Thread 獨享的,因此說可能在同一時刻在MySQL 中可能存在多個 sort buffer 內存區域。
在MySQL中filesort 的實現算法其實是有兩種:
雙路排序:是首先根據相應的條件取出相應的排序字段和能夠直接定位行數據的行指針信息,而後在sort buffer 中進行排序。
單路排序:是一次性取出知足條件行的全部字段,而後在sort buffer中進行排序。
在MySQL4.1版本以前只有第一種排序算法雙路排序,第二種算法是從MySQL4.1開始的改進算法,主要目的是爲了減小第一次算法中須要兩次訪問表數據的IO操做,將兩次變成了一次,但相應也會耗用更多的sortbuffer 空間。固然,MySQL4.1開始的之後全部版本同時也支持第一種算法。
MySQL主要經過比較咱們所設定的系統參數 max_length_for_sort_data的大小和Query 語句所取出的字段類型大小總和來斷定須要使用哪種排序算法。若是 max_length_for_sort_data更大,則使用第二種優化後的算法,反之使用第一種算法。因此若是但願 ORDER BY 操做的效率儘量的高,必定要注意max_length_for_sort_data 參數的設置。若是filesort過程當中,因爲排序緩存的大小不夠大,那麼就可能會致使臨時表的使用。 max_length_for_sort_data的默認值是1024。