MySQL數據庫索引詳解


一、什么是索引:

  索引是一個排序的列表,在這個列表中存儲着索引值和包含這個值的數據所在行的物理地址,在數據十分龐大的時候,索引可以大大加快查詢速度,這是因為使用索引后可以不用全表掃描來定位某行的數據,而是先通過索引表找到該行數據對應的物理地址然后訪問相應的數據。

  索引通過不斷縮小想要獲取數據的范圍來篩選出最終想要的結果,同時把隨機事件變成順序事件,也就是說,有個這個機制我們可以總是用同一種查找方式來鎖定數據;

  索引實際就是一張表,該表保存了主鍵和索引字段,並指向實體表的記錄,所以索引也是占了一大部分空間,不可能存儲在內存中,因此索引往往都是以文件形式存儲在我們的硬盤上。

在這個列表中存儲着索引的值和包含這個值的數據所在行的物理地址,在數據十分龐大的時候,索引可以大大加快查詢的速度,這是因為使用索引后可以不用掃描全表來定位某行的數據,而是先通過索引表找到該行數據對應的物理地址然后訪問相應的數據。

索引通過不斷地縮小想要獲取數據的范圍來篩選出最終想要的結果,同時把隨機事件變成順序事件,也就是說,有個這個機制我們可以總是用同一種查找方式來鎖定數據;

  索引實際就是一張表,該表保存了主鍵和索引字段,並指向實體表的記錄,所以索引也是占了一大部分空間,不可能存儲在內存中,因此索引往往都是以文件形式存儲在硬盤上。

二、索引的分類:

常見索引有主鍵索引、唯一索引、普通索引、全文索引和組合索引。

1、主鍵索引

主索引,根據pk_clolum(length)建立索引,不允許重復,不允許空值;

ALTER TABLE 'table_name' ADD PRIMARY KEY pk_index('col');

2、唯一索引

用來建立索引的列的值必須是唯一的,允許空值;

ALTER TABLE ‘table_name' ADD UNIQUE index_name('col');

3、普通索引

用表中的普通列構建的索引,沒有任何限制;

ALTER TABLE 'table_name' ADD INDEX index_name('col');

4、全文索引

用大文本對象的列構建的索引;

ALTER TABLE 'table_name' ADD INDEXD index_name('col');

5、組合索引

用多個列組合構建的索引,這多個列中的值不允許有空值;

ALTER TABLE 'table_name' ADD INDEX index_name('col');

三、SQL查詢計划詳解:

我們可以在select語句前添加explain來查詢MySQL的執行計划,下面是對explain的具體說明:

id SELECT識別符。這是SELECT的查詢序列號
select_type

查詢類型

SIMPLE:簡單的select(不使用UNION或子查詢)

PRIMARY:最外面的select

UNION:UNION中第二個或后面的SELECT語句

DEPEDENT UNION:UNION中第二個或后面的SELECT語句,取決於外面的查詢

UNION RESULT:UNION的結果

SUBQUERY:子查詢中的第一個SELECT

DEPENDENT SUBQUERY:子查詢中的第一個SELECT,取決於外面的查詢

DERIVED:導出表的SELECT(FROM字句的子查詢)

table 輸出行所引用的表
type

聯接類型

system:表僅有一行(=系統表)

const:表最多有一個匹配行,它將在查詢開始時被讀取。因為僅有一行,在這行的列值可被優化器剩余部分認為是常數。const表很快,因為它們只讀取一次

eq_ref:對於每個來自前面的表的行組合,從該表中讀取一行。這可能是最好的聯接類型,除了const類型

ref:對於每個來自前面的表的行組合,所有有匹配索引值的行將從這張表中讀取

ref_or_null:該聯接類型同ref,但是添加了MySQL可以專門搜索包含NULL值的行

index_merge:該聯接類型表示使用了索引合並優化方法

unique_subquery:該類型替換了下面形式的IN子查詢的ref:value In (SELECT primary_key FROM single_table WHERE some_expr)unique_subquery是一個索引查找函數,可以完全替換子查詢,效率更高

index_subquery:該聯接類型類似於unique_subquery。可以替換IN子查詢,但只適合下列形式的子查詢中的非唯一索引:value IN (SELECT key_column FROM single_table WHERE some_expr)

rang:只檢索指定范圍的行,使用一個索引來選擇行

index:該聯接類型與ALL相同,除了只有索引樹被掃描。這通常比ALL快,因為索引文件通常比數據文件小

ALL:對於每個來自先前的表的行組合,進行完整的表掃描

possible_keys 指出MySQL能使用哪個索引在該表中找到行
key 顯示MySQL實際使用的鍵(索引)。如果沒有選擇索引,鍵是NULL
key_len 顯示MySQL決定使用的鍵長度。如果沒有選擇索引,則長度為NULL
ref 顯示使用哪個列或常數與key一起從表中選擇行
rows 顯示MySQL認為它執行查詢時必須檢查的行數。多行之間的數據相乘可以估算要處理的行數
filtered 顯示了通過條件過濾出的行數的百分比估計值
Extra

MySQL解決查詢的詳細信息

Distinct:MySQL發現第1個匹配行后,停止為當前的行組合搜索更多的行

Not exists:MySQL能夠對查詢進行LEFT JOIN優化,發現1個匹配LEFT JOIN標准的行后,不再為前面的行組合在該表內檢查更多的行

range checked for each record(index map:#):MySQL沒有發現好的可以使用的索引,但發現如果來自前面的表的列值已知,可能部分索引可以使用

Using filesort:MySQL需要額外的一次傳遞,以找出如何按排序順序檢索行

Using index:從只使用索引樹中的信息而不需要進一步索引讀取實際的行來檢索表中的列信息

Using temporary:為了解決查詢,MySQL需要創建一個臨時表來容納結果

Using where:WHERE字句用於限制哪一個匹配下一個表或發送到客戶

Using sort_union(...),Using union(...),Using intersect(...):這些函數說明如何為index_merge聯接類型合並索引掃描

Using index for group-by:類似於訪問表的Using index方式,Using index for group-by表示MySQL發現了一個索引,可以用來查詢GROUP BY 或DISTINCT查詢的所有列,而不要額外索引硬盤訪問實際的表

type顯示的是訪問類型,是較為重要的一個指標,其中結果值從好到壞依次是:system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>ALL

一般我們在查詢的時候至少保證到range級別,最后達到ref。

四、索引失效

1、前導模糊查詢不能利用索引(like '%xxx' 或like '%xxx%')

2、使用or連接

3、使用不等號(!= 或者<>)

4、空值判斷(is null 或者is not null)

5、varchar類型在條件查詢時未加引號,導致隱式轉換

6、查詢所有(select *)

7、在索引列進行操作(計算、函數、類型轉換),會導致索引失效轉向全表掃描

8、使用not in 或者not exists

9、如果是左外連接或右外連接查詢時,兩張表的關聯字段編碼格式不一樣

10、如果聯合索引KEY 'name_index' ('name','code') Using BTREE沒有用到第一個索引字段,則不會走索引

11、使用between and 

12、當變量是times類型,而字段是date類型,索引失效;或相反情況也一樣失效

13、時間類型和varchar類型的索引比較

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM