概述
在目前這個大數據,大流量時代,我們的網站不光流量大,數據量也會非常的巨大。在巨大的數據量中精確找出我們需要的數據,這個對我們數據庫壓力比較大。而我們在不考慮進行分庫分表的操作時,進行SQL語句優化是一個很好的解決辦法,下面介紹explain
關鍵詞分析SQL語句,及使用索引進行優化查詢。
explain
關鍵字使用
explain
使用格式
EXPLAIN SELECT
*
FROM
SCORE
WHERE
CNO = '3-105'
AND DEGREE > (
SELECT
DEGREE
FROM
SCORE
WHERE
SNO = 109
)
查詢結果
id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra |
---|---|---|---|---|---|---|---|---|---|
1 | PRIMARY | SCORE | ALL | null | null | null | null | 12 | Using where |
2 | SUBQUERY | SCORE | ALL | null | null | null | null | 12 | Using where |
explain
表格各個屬性分析
id
:select查詢的序列號,包含一組數字,表示查詢中執行select子句或操作表的順序
- id相同時,執行順序由上至下
- id不同時,如果是子查詢,序號id會遞增,id值越大優先級越高,越先被執行,在所有組中,id值越大優先級越高
select_type
:查詢類別,主要是區別普通查詢,聯合查詢,子查詢等複雜查詢
simple
簡單查詢,不包含子查詢primary
:包含子查詢,爲最外層查詢subquery
:子查詢derived
:衍生表,虛擬表union
:出現union關鍵字union select
:在union結果中查詢
table
:查詢的表名type
:執行計劃包含的信息,顯示查詢使用了何種類型
type類型從最好到最差
system > const > eq_ref > ref > range >index > all
system
:表中只有一條記錄(等於系統表),這是const
類型的特例,平時不會出現,這個可以忽略不計。const
:表示通過索引一次就找到了,const
用於比較primary key
或者union
索引,因爲只匹配一行數據,所以很快,如將主鍵置於where中。eq_ref
:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見主鍵或者唯一索引掃描ref
:非唯一索引掃描,返回匹配條件的所有行。本質上也是一種索引,他返回所有匹配某個單獨值得所有行,然而,他可能會找到多個符合條件得行,所以他應該屬於查找和掃描得混合體。range
:只檢索給定範圍的行,使用索引來選擇行。key列顯示使用了哪些索引,一般就在你的where語句中出現了between、<、>、in等查詢,這種範圍掃描比全表掃描要好,因爲它只需要開始於索引的某一個點,而結束於某一個點,不用全表掃描。index
:full index scan,index
和all
的區別爲index
類型只遍歷索引樹。這通常比all
快,因爲索引文件通常比數據文件小(也就是說雖然all
和index
都是全表掃描,但是index
是從索引文件中進行掃描,all
是通過硬盤中讀取的)all
:全表掃描
possible_keys
:顯示可能應用於查詢的索引,一個或者多個。查詢涉及到字段存在索引,則將索引列出,但不一定在查詢中使用。key
:實際查詢使用的索引。如果爲null
,則沒有用到索引,若使用到了覆蓋索引,則該索引只出現在key
列表中。key_len
:顯示索引中使用的字節數,可通過該列計算查詢中使用到索引長度。在不損失精度下,長度越短越好。key_len
顯示的值爲索引字段的最大長度,並非實際使用長度,即key_len
是根據表定義計算而得,不是通過表內檢索出得。ref
:顯示索引的哪一列被使用了,如果可能的話,是一個常數。哪些列或者常量被用於查找索引列上值。rows
:根據表統計信息及索引選用情況,大致估算出找到所需的記錄需要讀取的行數extra
:不適合在其他列中顯示,但又十分重要的信息
using filesort
:說明MySQL會對數據使用一個外部的索引排序,而不是按照表內索引進行讀取。MySQL中無法利用索引完成排序操作稱之爲文件排序
。如果出現這種情況,查詢將會非常的慢using temporary
:說明使用臨時表保存中間結果,MySQL在對查詢結果進行排序時,使用臨時表。常見於排序order by
和group by
。出現這種情況查詢會非常慢。using index
:表示相應的select操作中使用覆蓋索引(covering index),避免訪問數據行,效率很好!如果同時出現using where
,表明索引被用來執行索引值查找;如果沒有同時出現using where
,表明索引用來讀取非執行查找動作。using where
:使用where
關鍵字查找impossible where
:子句的值總的false,不能用來獲取任何元組
索引優化案例
- 單表建立索引,查詢的字段不要出現範圍否則會出現索引失效的情況
- 兩個表連接查詢建立索引,索引一般建在從表上,左連接,建立在右邊;右連接,建立在左邊。
索引失效情況(應該避免)
- 全值匹配我最愛(查詢條件完全符合索引順序)
- 最佳左前綴法則:如果索引了多列,要遵守最左前綴法則。指的是查詢從索引的最左列開始並且 不跳過索引列(類別火車,火車頭)
- 不能在所有列上做任何操作(計算,函數,(自動or手動)類型轉換),會導致索引失效,導致全表掃描
- 存儲引擎不能使用索引中範圍條件右邊的列
- 儘量使用覆蓋索引(只訪問索引的查詢),減少select *
- 在使用不等於(!= 或者<>)的時候無法使用索引導致全表掃描
- is null 或者is not null 也無法使用索引
- like以通配符開頭(’%abcd’),MySQL索引會失效會變成全表掃描
- 字符串不加單引號索引也會失效
- 少用or,用了它連接會導致索引失效
阿里巴巴規範
- 推薦】:SQL性能優化的目標:至少要達到
rang
級別,要求是ref
級別,如果可以是consts
最好。
說明:consts
單表中最多隻有一個匹配行(主鍵或者唯一索引),在優化階段即可讀取到數據。
ref
指的是使用普通的索引(normal index)
rang
對索引進行範圍檢索
反例:explain表的結果,type=index,索引物理文件全掃描,速度非常慢,這個index級別比較range還低,與全表掃描是小巫見大巫