1. 程式人生 > 其它 >mysql索引詳解

mysql索引詳解

  索引是對資料庫表中一列或多列的值進行排序的一種結構。MySQL索引的建立對於MySQL的高效執行是很重要的,索引可以大大提高MySQL的檢索速度。索引只是提高效率的一個因素,如果你的MySQL有大資料量的表,就需要花時間研究建立最優秀的索引,或優化查詢語句。

 

索引的優點

索引大大減小了伺服器需要掃描的資料量,從而大大加快資料的檢索速度,這也是建立索引的最主要的原因。
索引可以幫助伺服器避免排序和建立臨時表
索引可以將隨機IO變成順序IO
索引對於InnoDB(對索引支援行級鎖)非常重要,因為它可以讓查詢鎖更少的元組,提高了表訪問併發性
關於InnoDB、索引和鎖:InnoDB在二級索引上使用共享鎖(讀鎖),但訪問主鍵索引需要排他鎖(寫鎖)
通過建立唯一性索引,可以保證資料庫表中每一行資料的唯一性。
可以加速表和表之間的連線,特別是在實現資料的參考完整性方面特別有意義。
在使用分組和排序子句進行資料檢索時,同樣可以顯著減少查詢中分組和排序的時間。
通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的效能。

 

缺點

建立索引和維護索引要耗費時間,這種時間隨著資料量的增加而增加
索引需要佔物理空間,除了資料表佔用資料空間之外,每一個索引還要佔用一定的物理空間,如果需要建立聚簇索引,那麼需要佔用的空間會更大
對錶中的資料進行增、刪、改的時候,索引也要動態的維護,這就降低了整數的維護速度
如果某個資料列包含許多重複的內容,為它建立索引就沒有太大的實際效果。
對於非常小的表,大部分情況下簡單的全表掃描更高效;

 

建立索引準則

 

應該建立索引的列:

在經常需要搜尋的列上,可以加快搜索的速度
在作為主鍵的列上,強制該列的唯一性和組織表中資料的排列結構
在經常用在連線(JOIN)的列上,這些列主要是一外來鍵,可以加快連線的速度
在經常需要根據範圍(
<,<=,=,>,>=,BETWEEN,IN)進行搜尋的列上建立索引,因為索引已經排序,其指定的範圍是連續的 在經常需要排序(order by)的列上建立索引,因為索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間; 在經常使用在WHERE子句中的列上面建立索引,加快條件的判斷速度。



不應該建立索引的列

對於那些在查詢中很少使用或者參考的列不應該建立索引。
若列很少使用到,因此有索引或者無索引,並不能提高查詢速度。相反,由於增加了索引,反而降低了系統的維護速度和增大了空間需求。
對於那些只有很少資料值或者重複值多的列也不應該增加索引。
這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的資料行佔了表中資料行的很大比例,即需要在表中搜索的資料行的比例很大。增加索引,並不能明顯加快檢索速度。
對於那些定義為text, image和bit資料型別的列不應該增加索引。
這些列的資料量要麼相當大,要麼取值很少。
當該列修改效能要求遠遠高於檢索效能時,不應該建立索引。(修改效能和檢索效能是互相矛盾的)

 

索引分類

主鍵索引:一張表只能有一個主鍵索引,不允許重複、不允許為 NULL;

ALTER TABLE TableName ADD PRIMARY KEY(column_list); 

 

唯一索引:資料列不允許重複,允許為 NULL 值,一張表可有多個唯一索引,索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。

CREATE UNIQUE INDEX IndexName ON `TableName`(`欄位名`(length));
# 或者
ALTER TABLE TableName ADD UNIQUE (column_list);

 

普通索引:一張表可以建立多個普通索引,一個普通索引可以包含多個欄位,允許資料重複,允許 NULL 值插入;

CREATE INDEX IndexName ON `TableName`(`欄位名`(length));
# 或者
ALTER TABLE TableName ADD INDEX IndexName(`欄位名`(length));

 

聚簇索引(clustered index)不是單獨的一種索引型別,而是一種資料儲存方式。這種儲存方式是依靠B+樹來實現的,根據表的主鍵構造一棵B+樹且B+樹葉子節點存放的都是表的行記錄資料時,方可稱該主鍵索引為聚簇索引。聚簇索引也可理解為將資料儲存與索引放到了一塊,找到索引也就找到了資料。

非聚簇索引:資料和索引是分開的,B+樹葉子節點存放的不是資料表的行記錄。

 

建立索引

-- 建立普通索引 
CREATE INDEX index_name ON table_name(col_name);

-- 建立唯一索引
CREATE UNIQUE INDEX index_name ON table_name(col_name);

-- 建立普通組合索引
CREATE INDEX index_name ON table_name(col_name_1,col_name_2);

-- 建立唯一組合索引
CREATE UNIQUE INDEX index_name ON table_name(col_name_1,col_name_2);


 

修改表結構建立索引

ALTER TABLE table_name ADD INDEX index_name(col_name);

 

建立表時直接指定索引

CREATE TABLE table_name (
    ID INT NOT NULL,
    col_name VARCHAR (16) NOT NULL,
    INDEX index_name (col_name)
);

 

刪除索引

-- 直接刪除索引
DROP INDEX index_name ON table_name;

-- 修改表結構刪除索引
ALTER TABLE table_name DROP INDEX index_name;

 

索引失效

1、索引不儲存null值
更準確的說,單列索引不儲存null值,複合索引不儲存全為null的值。索引不能儲存Null,所以對這列採用is null條件時,因為索引上根本

沒Null值,不能利用到索引,只能全表掃描。

為什麼索引列不能存Null值?
將索引列值進行建樹,其中必然涉及到諸多的比較操作。Null值的特殊性就在於參與的運算大多取值為null。

這樣的話,null值實際上是不能參與進建索引的過程。也就是說,null值不會像其他取值一樣出現在索引樹的葉子節點上。



2.不適合鍵值較少的列(重複資料較多的列) 假如索引列TYPE有5個鍵值,如果有1萬條資料,那麼 WHERE TYPE = 1將訪問表中的2000個數據塊。 再加上訪問索引塊,一共要訪問大於200個的資料塊。 如果全表掃描,假設10條資料一個數據塊,那麼只需訪問1000個數據塊,既然全表掃描訪問的資料塊 少一些,肯定就不會利用索引了。

3.前導模糊查詢不能利用索引(like '%XX'或者like '%XX%') 假如有這樣一列code的值為'AAA','AAB','BAA','BAB' ,如果where code like '%AB'條件,由於前面是 模糊的,所以不能利用索引的順序,必須一個個去找,看是否滿足條件。這樣會導致全索引掃描或者全表掃 描。如果是這樣的條件where code like 'A % ',就可以查詢CODE中A開頭的CODE的位置,當碰到B開頭的 資料時,就可以停止查找了,因為後面的資料一定不滿足要求。這樣就可以利用索引了。 也可以通過反轉字串進行拼接 reverse('%易不楊') 最終會為 楊不易

4.索引失效的幾種情況 1.如果條件中有or,即使其中有條件帶索引也不會使用(這也是為什麼儘量少用or的原因) 要想使用or,又想讓索引生效,只能將or條件中的每個列都加上索引 2.對於多列索引,不是使用的第一部分,則不會使用索引 3.like查詢以%開頭 4.如果列型別是字串,那一定要在條件中將資料使用引號引用起來,否則不使用索引 5.如果mysql估計使用全表掃描要比使用索引快,則不使用索引

 

最左字首原則

最左字首其實說的是,在where條件中出現的欄位,如果只有組合索引中的部分列,則這部分列的觸發索引順序,是按照定義索引的時候的順序從前到後觸發,最左面一個列觸發不了,之後的所有列索引都無法觸發。

就比如索引順序是(a,b,c),查詢的組合條件就只有(a,b),(a,c),(b,c)其中就只有bc是不生效的