MySQL:explain(執行計劃)詳解
阿新 • • 發佈:2019-02-17
本文主要介紹了MySQL效能分析以及explain的使用,
包括:組合索引、慢查詢分析、MYISAM和INNODB的鎖定、MYSQL的事務配置項等
索引類似大學圖書館建書目索引,可以提高資料檢索的效率,降低資料庫的IO成本。MySQL在300萬條記錄左右效能開始逐漸下降,雖然官方文件說500~800w記錄,所以大資料量建立索引是非常有必要的。MySQL提供了Explain,用於顯示SQL執行的詳細資訊,可以進行索引的優化。
導致SQL執行慢的原因:
1.硬體問題。如網路速度慢,記憶體不足,I/O吞吐量小,磁碟空間滿了等。
2.沒有索引或者索引失效。(一般在網際網路公司,DBA會在半夜把表鎖了,重新建立一遍索引,因為當你刪除某個資料的時候,索引的樹結構就不完整了。所以網際網路公司的資料做的是假刪除.一是為了做資料分析,二是為了不破壞索引 )
3.資料過多(分庫分表)
4.伺服器調優及各個引數設定(調整my.cnf)
分析原因時,一定要找切入點:
1.先觀察,開啟慢查詢日誌,設定相應的閾值(比如超過3秒就是慢SQL),在生產環境跑上個一天過後,看看哪些SQL比較慢。
2.Explain和慢SQL分析。比如SQL語句寫的爛,索引沒有或失效,關聯查詢太多(有時候是設計缺陷或者不得以的需求)等等。
3.Show Profile是比Explain更近一步的執行細節,可以查詢到執行每一個SQL都幹了什麼事,這些事分別花了多少秒。
4.找DBA或者運維對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 表示沒用到索引。
type=ref 因為這時認為是多個匹配行,在聯合查詢中,一般為REF。
2.MYSQL中的組合索引
- 假設表有id,key1,key2,key3,把三者形成一個組合索引,則如:
where key1=....
where key1=1 and key2=2
where key1=3 and key2=3 and key3=2
- 根據最左字首原則,這些都是可以使用索引的,如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的話則不同了,用的是行鎖,不存在上面問題。
MyISAM和InnoDB講解
InnoDB和MyISAM是許多人在使用MySQL時最常用的兩個表型別,這兩個表型別各有優劣,視具體應用而定。
基本的差別為:
MyISAM型別不支援事務處理等高階處理,而InnoDB型別支援。
MyISAM型別的表強調的是效能,其執行數度比InnoDB型別更快,但是不提供事務支援,
而InnoDB提供事務支援以及外部鍵等高階資料庫功能。
以下是一些細節和具體實現的差別:
◆1.InnoDB不支援FULLTEXT型別的索引。
◆2.InnoDB中不儲存表的具體行數,也就是說,執行select count(*) from table時,
InnoDB要掃描一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出儲存好的行數即可。
注意的是,當count(*)語句包含 where條件時,兩種表的操作是一樣的。
◆3.對於AUTO_INCREMENT型別的欄位,InnoDB中必須包含只有該欄位的索引,
但是在MyISAM表中,可以和其他欄位一起建立聯合索引。
◆4.DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除。
◆5.LOAD TABLE FROM MASTER操作對InnoDB是不起作用的,
解決方法是首先把InnoDB表改成MyISAM表,匯入資料後再改成InnoDB表,
但是對於使用的額外的InnoDB特性(例如外來鍵)的表不適用。
另外,InnoDB表的行鎖也不是絕對的,假如在執行一個SQL語句時MySQL不能確定要掃描的範圍,InnoDB表同樣會鎖全表,
例如update table set num=1 where name like “%aaa%”
兩種型別最主要的差別就是Innodb支援事務處理與外來鍵和行級鎖。
而MyISAM不支援.所以MyISAM往往就容易被人認為只適合在小專案中使用。
作為使用MySQL的使用者角度出發,Innodb和MyISAM都是比較喜歡的,
如果資料庫平臺要達到需求:99.9%的穩定性,方便的擴充套件性和高可用性來說的話,MyISAM絕對是首選。
原因如下:
1、平臺上承載的大部分專案是讀多寫少的專案,而MyISAM的讀效能是比Innodb強不少的。
2、MyISAM的索引和資料是分開的,並且索引是有壓縮的,記憶體使用率就對應提高了不少。
能載入更多索引,而Innodb是索引和資料是緊密捆綁的,
沒有使用壓縮從而會造成Innodb比MyISAM體積龐大不小。
3、經常隔1,2個月就會發生應用開發人員不小心update一個表where寫的範圍不對,導致這個表沒法正常用了,
這個時候MyISAM的優越性就體現出來了,隨便從當天拷貝的壓縮包取出對應表的檔案,
隨便放到一個數據庫目錄下,
然後dump成sql再導回到主庫,並把對應的binlog補上。
如果是Innodb,恐怕不可能有這麼快速度,別和我說讓Innodb定期用匯出xxx.sql機制備份,
因為最小的一個數據庫例項的資料量基本都是幾十G大小。
4、從接觸的應用邏輯來說,select count(*)和order by 是最頻繁的,大概能佔了整個sql總語句的60%以上的操作,
而這種操作Innodb其實也是會鎖表的,很多人以為Innodb是行級鎖,那個只是where對它主鍵是有效,非主鍵的都會鎖全表的。
5、還有就是經常有很多應用部門需要我給他們定期某些表的資料,MyISAM的話很方便,只要發給他們對應那表的frm.MYD,MYI的檔案,
讓他們自己在對應版本的資料庫啟動就行,而Innodb就需要匯出xxx.sql了,因為光給別人檔案,受字典資料檔案的影響,對方是無法使用的。
6、如果和MyISAM比insert寫操作的話,Innodb還達不到MyISAM的寫效能,如果是針對基於索引的update操作,
雖然MyISAM可能會遜色Innodb,但是那麼高併發的寫,從庫能否追的上也是一個問題,還不如通過多例項分庫分表架構來解決。
7、如果是用MyISAM的話,merge引擎可以大大加快應用部門的開發速度,
他們只要對這個merge表做一些select count(*)操作,非常適合大專案總量約幾億的rows某一型別(如日誌,調查統計)的業務表。
當然Innodb也不是絕對不用,用事務的專案就用Innodb的。
另外,可能有人會說你MyISAM無法抗太多寫操作,但是可以通過架構來彌補。
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查詢的序列號
--id相同,執行順序由上而下
--id不同,值越大越先被執行
- select_type:select查詢的型別,主要是區別普通查詢和聯合查詢、子查詢之類的複雜查詢。
a.SIMPLE:查詢中不包含子查詢或者UNION
b