1.索引
1.1.定義
MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構。
我們平常所說的索引,如何沒有特別的指明,都是B樹(多路搜索樹,並不一定是二叉的)結構組織索引,其中聚集索引,次要索引,覆蓋索引,複合索引,前綴索引,唯一索引默認都是使用B+樹索引,統稱索引,當然除了B+數這種類型的索引外還有(hash索引等)
1.2.優劣勢
索引
優勢:
類似大學圖書館建書目索引,提高數據檢索的效率,降低數據IO成本
通過索引列對數據排序,降低數據排序的成本,降低CPU的消耗
劣勢:
實際上索引也是一張表,該表保存了主鍵和索引字段,並指向實體表的記錄,所以索引也是要佔空間的
雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進INSERT、UPDATE和DELETE。因爲更新表時,MySQL不僅 要保存數據,還要保存一下索引文件每次更新添加了索引列的字段,都會調整因爲更新所帶來的鍵值變化後的索引信息
索引只是提高效率的一個因素,如果你的MySQL有大數據量的表,就需要花時間研究建立最優秀的索引,或優化查詢
1.3.索引分類
單值索引:一個索引只包含單個列,一個表可以有多個單列索引
唯一索引:索引列的值必須唯一,但允許有空值
複合索引:一個索引包含多個列
基本語法:
創建:
CREATE [UNIQUE] INDEX indexName ON mytable(columnname(length)) ALTER mytable add[unique] index [indexname] on (columnname(length))
刪除:
DROP INDEX[INDEXNAME] ON Mytable
查看:
show index from table_name\G
使用ALTER命令:
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list) #該語句添加一個主鍵,這意味着索引值必須是唯一的,且不能爲NULL ALTER TABLE tbl_name ADD UNIQUE index_name (column_list) #這條語句創建索引的值必須是唯一的(除了NULL外,NULL可能會出現多次) ALTER TABLE tbl_name ADD INDEX index_name (column_list) #添加普通索引,索引值可出現多次 ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list) #該語句指定了索引爲FULLTEXT,用於全文索引
1.4.索引使用場景
哪些情況需要創建索引:
1.主鍵自動建立唯一索引;
2.頻繁作爲查詢條件的字段應該創建索引;
3.查詢中與其它表關聯的字段,外鍵關係建立索引;
4.頻繁更新的字段不適合創建索引-因爲每次更新不單單是更新了記錄還會更新索引;
5. Where條件裏用不到的字段不創建索引;
6.單鍵/組合索引的選擇問題,who? (在高併發下傾向創建組合索引);
7.查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度;
8.查詢中統計或者分組字段
哪些情況不要創建索引:
1.表記錄太少;
2.經常增刪改的表;
3.數據重複且分佈平均的表字段,因此應該只爲最經常查詢和最經常排序的數據列建立索引。
注意,如果某個數據列包含許多重複的內容,爲它建立索引就沒有太大的實際效果。
2.Explain性能分析
使用Explain關鍵字可以模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句,分析你的查詢語句或是表結構的性能瓶頸。
具體分析結果包含:表的讀取順序、數據的讀取操作的操作類型、哪些索引可以使用、哪些索引被實際使用、表之間的引用、每張表有多少行被優化器查詢
2.1.id(執行順序)
explain + sql 執行之後會顯示如下信息列,表示mysql執行當前sql的執行信息。
id:select查詢的序列號,包含一組數字,表示查詢中執行select子句或操作表的順序
id顯示的執行順序一共有三種情況:
①id相同,執行順序由上至下;
②id不同,如果是子查詢,id序號會遞增,id值越大優先級越高,越優先被執行
③id相同與不同,同時存在
2.2.select_type(查詢類型)
select_type:表示查詢的類型,主要是用於區別該條sql語句是普通查詢、聯合查詢、子查詢等的複雜查詢
select_type的類型有以下幾種:
SIMPLE:簡單的select查詢,查詢中不包含子查詢或者union;
PRIMARY:查詢中若包含任何複雜的子部分,最外層則被標記爲;
SUBQUERY:在select或where列表中包含子查詢;
DERIVED:在FROM列表中包含子查詢被標記爲DERIVED (衍生) MYSQL會遞歸執行這些子查詢,把結果放在臨時表中
UNION:若第二個SELECT出現在UNION之後,則被標記爲UNION,若UNION包含在FROM子句的子查詢中,外層SELECT將被標記爲DERIVED
UNION RESULT:從UNION表獲取結果的SELECT
2.3.Table
table用於顯示這一行數據是來自哪一張表的
2.4.Type
type顯示的是訪問類型,是較爲重要的一個指標,主要的類型有:
一般在實際開發中,結果值從最好到最壞依次是:
system > const > eq_ref > ref > range > index > ALL
一般來說,sql優化得保證查詢至少達到range級別,最好能達到ref。
system:表中只有一行記錄(等於系統表),這是const類型的特例,平時不會出現,這個也可以忽略不計;
const:表示通過索引一次就找到了,const用於比較primary key 或者unique索引,因爲只匹配一行數據,所以很快將主鍵置於where列表中,MySQL就能將該查詢轉換爲一個常量
eq_ref:唯一索引掃描,對每個索引鍵,表中只有一條記錄與之匹配,常見於主鍵或唯一索引掃描
ref:非唯一性索引掃描,返回匹配的某個單獨值所有行,本質上也是一種索引訪問,
它返回所有匹配單個單獨值的行,然而他可能會找到多個符合條件的行,所以他應該屬於查找和掃描的混合體
range:只檢索給定範圍的行,使用一個索引來選擇行,key列顯示使用了哪個索引,一般就是在where語句中出現了between、<>、in等查詢,這種範圍掃描比
全表掃描要好,因爲它開始於索引的某一點而結束於另一點,不用掃描全部索引
index:index與ALL區別爲index類型值遍歷索引,通常比ALL快,因爲索引文件通常比數據文件小
(all和index都是讀全表,但index是從索引中讀取的,而all是從硬盤中讀的)
all:全表掃描,將遍歷全表以找到匹配的行
2.5.possible_keys/key
possible_keys:顯示可能應用在這張表中的索引,一個或多個查詢設計到的字段上若存在索引,則該索引將被列出,但不一定被查詢實際使用
key:實際使用的索引,如果爲NULL,則沒有使用索引
注意:查詢中若使用了覆蓋索引,則該索引僅出現在key列表中
2.6.key_len
key_len:表示索引中使用的字節數,可通過該列計算查詢中使用的索引長度,在不損失精確性的情況下,長度越短越好
key_len顯示的值爲索引字段的最大可能長度,並非實際使用長度,及key_len是根據表定義計算而得,而不是通過表內檢索出的
原則:同一檢索條件下,key_len長度越短越好,消耗小、性能高。
2.7.ref
ref:顯示索引的那一列被使用了,如果可能的話,是一個常數,那些列或常量被用於查找所有列上的值
2.8.rows
rows:根據表統計信息及索引選用情況,大致估算出找到所需的記錄所需要的讀取行數
2.9.Extra
extra:包含不適合在其它列中顯示但十分重要的額外信息,主要類型有:
Using filesort:說明mysql會對數據使用一個外部索引排序,而不是按照表內的索引順序進行讀取,MySQL中無法利用索引完成的排序操作稱爲“文件排序”
Using temporary:使用臨時表保存了中間結果,MySQL在對查詢結果排序時時使用臨時表,常見於排序order by 和分組查詢group by
Using index:表示相應的select操作中使用了覆蓋索引(Covering Index) 避免訪問了表的數據行,效率不錯,如果同時出現using where 表明索引被用來執行索引鍵值的查找。如果沒有出現using where 表明該索引用來讀取數據而非執行查找動作
覆蓋索引:又名索引覆蓋,就是select的數據列只用從索引中就能獲取,不必讀取數據行,MySQL可以利用索引返回select列表中的字段,而不必根據索引再次讀取數據文件,換句話說查詢列要被所建的索引覆蓋。
Using where:表示where連接
Using join buffer:表示使用了連接緩存