用MySql的查询分析语法explain来优化查询和索引
http://hi.baidu.com/wtnzone/item/beb83840a4971af4dd0f6c77
數據庫最常見的操作就是查詢了,我們經常要用"SELECT"語法對已有的表進行某種檢索,但是在實際應用中,查詢前我們并不知道該查詢會如何運行、會使用多少時間、會涉及多少字段和記錄,每次輸入了SQL語句,點擊運行,然后慢慢等待結果的出現,好的查詢語句效率很高,而有時候也會遇到查詢緩慢,久久沒有運行完成的情況。
由于我們并不知道實際查詢的時候數據庫里發生了什么,數據庫軟件是怎樣掃描表、怎樣使用索引,因此我們能感知的就只有查詢運行的時間,而往往在數據規模不大時,查詢是瞬間的,因此在寫SQL語句時也就比較隨意,也很少使用索引來加速查詢的速度。不過一旦數據規模增大,比如百萬、千萬、幾億的時候,我們寫同樣的查詢語句卻發現窗口遲遲沒有結果,這個時候才知道數據規模已經限制了我們自由查詢的速度。查詢優化和索引也就顯得很重要了。
那么,能不能在查詢前就能預先估計查詢究竟要涉及多少行、使用哪些索引、運行多久呢?答案是可以的,MySql和SQL Server都提供了相應的功能和語法來實現,下面用一個擁有兩千多萬條記錄的表來說明如何進行查詢分析。該表有一個訪問時間字段。
MySql提供了EXPLAIN語法用來進行查詢分析,在SQL語句前加一個"EXPLAIN"即可。比如我們要分析如下SQL語句,該語句獲取特定時間段的訪問記錄總數。
EXPLAIN
SELECT COUNT(*) FROM ××××××
WHERE
TIME_INT>=UNIX_TIMESTAMP('2010-03-01 18:00:00') AND?
TIME_INT<UNIX_TIMESTAMP('2010-03-01 18:15:00')
返回的結果如下
從分析結果可知,該查詢涉及3674行,用到了timeindex這個索引,using index說明該查詢只需要檢索索引即可完成。EXPLAIN中每一項的具體描述和表達的意義如下:(來自http://www.phpweblog.net/richard-dong/archive/2008/12/15/6173.aspx)
------------------------------
table | type | possible_keys | key | key_len | ref | rows | Extra
EXPLAIN列的解釋
table?
顯示這一行的數據是關于哪張表的
type?
這是重要的列,顯示連接使用了何種類型。從最好到最差的連接類型為const、eq_reg、ref、range、indexhe和ALL(后面有詳細說明)
possible_keys?
顯示可能應用在這張表中的索引。如果為空,沒有可能的索引。可以為相關的域從WHERE語句中選擇一個合適的語句
key?
實際使用的索引。如果為NULL,則沒有使用索引。很少的情況下,MYSQL會選擇優化不足的索引。這種情況下,可以在SELECT語句中使用USE INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MYSQL忽略索引
key_len?
使用的索引的長度。在不損失精確性的情況下,長度越短越好
ref?
顯示索引的哪一列被使用了,如果可能的話,是一個常數
rows?
MYSQL認為必須檢查的用來返回請求數據的行數
Extra?
關于MYSQL如何解析查詢的額外信息。將在表4.3中討論,但這里可以看到的壞的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,結果是檢索會很慢
extra列返回的描述的意義
Distinct?
一旦MYSQL找到了與行相聯合匹配的行,就不再搜索了
Not exists?
MYSQL優化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標準的行,就不再搜索了
Range checked for each
Record(index map:#)?
沒有找到理想的索引,因此對于從前面表中來的每一個行組合,MYSQL檢查使用哪個索引,并用它來從表中返回行。這是使用索引的最慢的連接之一
Using filesort?
看到這個的時候,查詢就需要優化了。MYSQL需要進行額外的步驟來發現如何對返回的行排序。它根據連接類型以及存儲排序鍵值和匹配條件的全部行的行指針來排序全部行
Using index?
列數據是從僅僅使用了索引中的信息而沒有讀取實際的行動的表返回的,這發生在對表的全部的請求列都是同一個索引的部分的時候
Using temporary?
看到這個的時候,查詢需要優化了。這里,MYSQL需要創建一個臨時表來存儲結果,這通常發生在對不同的列集進行ORDER BY上,而不是GROUP BY上
Where used?
使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給用戶。如果不想返回表中的全部行,并且連接類型ALL或index,這就會發生,或者是查詢有問題
不同連接類型的解釋(按照效率高低的順序排序)
system?
表只有一行:system表。這是const連接類型的特殊情況
const?
表中的一個記錄的最大值能夠匹配這個查詢(索引可以是主鍵或惟一索引)。因為只有一行,這個值實際就是常數,因為MYSQL先讀這個值然后把它當做常數來對待
eq_ref?
在連接中,MYSQL在查詢時,從前面的表中,對每一個記錄的聯合都從表中讀取一個記錄,它在查詢使用了索引為主鍵或惟一鍵的全部時使用
ref?
這個連接類型只有在查詢使用了不是惟一或主鍵的鍵或者是這些類型的部分(比如,利用最左邊前綴)時發生。對于之前的表的每一個行聯合,全部記錄都將從表中讀出。這個類型嚴重依賴于根據索引匹配的記錄多少—越少越好
range?
這個連接類型使用索引返回一個范圍中的行,比如使用>或<查找東西時發生的情況
index?
這個連接類型對前面的表中的每一個記錄聯合進行完全掃描(比ALL更好,因為索引一般小于表數據)
ALL?
這個連接類型對于前面的每一個記錄聯合進行完全掃描,這一般比較糟糕,應該盡量避免
------------------------------
弄明白了explain語法返回的每一項結果,我們就能知道查詢大致的運行時間了,如果查詢里沒有用到索引、或者需要掃描的行過多(比如>=幾十萬行),那么可以感到明顯的延遲。因此需要改變查詢方式或者新建索引。
比如沒有建索引,或者查詢寫得不好(沒有用到索引列),會造成如下掃描所有兩千多萬條記錄的查詢方案(type為"ALL",rows有兩千多萬),這顯然是不可取的,運行的話至少需要一分鐘的時間。
而一旦使用了索引,情況會大大改變,如下
這個時候最多掃描2624條記錄,使用了索引timeindex,同時extra里有Using index,表明了列數據是從僅僅使用了索引中的信息而沒有讀取實際的行動的表返回的,查詢速度也成千上萬倍的提升,不到0.1秒。
因此MySql中的explain語法可以幫助我們改寫查詢,優化表的結構和索引的設置,從而最大地提高查詢效率。當然,在大規模數據量時,索引的建立和維護的代價也是很高的,往往需要較長的時間和較大的空間,如果在不同的列組合上建立索引,空間的開銷會更大。因此索引最好設置在需要經常查詢的字段中。
------------------------------
不僅是MySql,每個主流數據庫都有相應的查詢分析的功能,比如SQL Server具有強大的圖形化分析功能,暫時還沒有深入研究,所以就放幾張圖吧。它不僅能仔細分析出查詢的細節,連CPU使用、IO消耗等等都能進行估計
=======http://my.oschina.net/phpnew/blog/151194
優秀的sqlyog, 我深深地感到不安及自責, 盜版用戶多年, 多少有點感覺過意不去, 希望富二代們能夠支持正版吧.
最近osc還在討論什么是php大牛, 以前看過帖子, 說得非常貼切. phper, 半個運維工程師, 半個dba, 半個前端設計, 半個js動畫, 半個市場營銷. 如果你的公司想發展, 請招一個phper, 全能型人才哪里找, 山東可以找藍翔, osc找phper.
回正題, 作為phper,當然在dba方面也要熟悉, 本人基礎知識薄弱, 才疏學淺, 對sqlyog研究未盡深刻, 有錯誤的地方請指點.
Sqlyog 盜版機制做得還是不錯的, 官網都不提供旗艦版下載, 可"優秀"的中國人更為強大, 這不v11.13都已經完美兼容. 有需要的同學上這兒下載:?http://www.fenanr.com/read/112140.html
簡單的寫一句查詢語句, 然后點擊左上角那個執行, 或者按F12, 結果頁將會顯示出數據. 如果你使用過舊版, 發現數據顯示后, 是可以編輯的. 而新版本拋棄了這個默認設置, 我個人覺得是非常合理的.我們先是想看看, 再決定是否修改.sqlyog這點人性化考慮非常細膩.
作為優秀的編輯器, 總是需要思考用戶所想, 有時我們在編寫sql時, 是不是想它提示出字段名呢? sqlyog在這方面做得非常強大. 可以提示字段名, 函數, 關鍵字,元素, 數據表,
我大概歸類了一下: f: 函數.? c: 字段名. k:關鍵字.? 余下一種就是數據表. 這對于許多sql編寫者來說, 是非常方便的功能.
性能優化才是互聯網技術人員的關鍵, 優化得力可以讓速度翻倍, 那我們怎么知道一條sql性能如何呢? sqlyog可以快速為語句檢測一次解釋. 也就是explain的語法.?
執行后配置文件頁將顯示出結果. 具體怎么看這表, soso吧.
在phpmyadmin中, 我們碰到個問題就是, 我希望可以一次性寫多條語句, 可以分開執行. 而不需要清空編輯器. sqlyog就非常智能的解決了這個問題. 你可以在編輯器中寫無數條sql, 只要記得結束加分號.
鼠標光標所在的那一條, 將會被執行. 也就是你點到哪, 就執行哪一句. 這樣你就可以一條語句延伸N條test語句, 直觀地運行查看性能結果.?
無論多少條語句, 編寫的智能提示仍然有效.
常用的四條語句, 有時要完全寫出來, 還真不是件容易的事, 而在sqlyog中就容易了, 直接界面操作, 或者按快捷鍵.
?系統默認釋放的sql, 可能跟你想像中的不太一樣, 或許不夠直觀, 特別在過程,聯表, 觸發器語句中, 格式化查詢后的效果會非常明顯.
當在創建臨時表語句中, 會碰到許多里里外外的分號, 也就把sql給分隔了, 導致執行失敗. sqlyog當然不會犯這種低級錯誤, 而是需要把語句選擇起來執行, 如圖片所示.
圖片中演示的是一次性將兩條語句執行起來. 下面會出現二個結果頁. 分別代表每語句的結果. 這功能相信你不會錯過.
我想,sqlyog 更為強大的是歷史記錄功能, 非常明了的列表, 執行時間, 執行效率.
總結
以上是生活随笔為你收集整理的用MySql的查询分析语法explain来优化查询和索引的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iBatis resultMap出错 T
- 下一篇: MongoDB 里面日期查询的问题