索引的使用,最左字首原則

2021-09-26 23:16:05 字數 4708 閱讀 9648

建立索引可以大大提高系統的效能。

第一,通過建立唯一性索引,可以保證資料庫表中每一行資料的唯一性。

第二,可以大大加快資料的檢索速度,這也是建立索引的最主要的原因。

第三,可以加速表和表之間的連線,特別是在實現資料的參考完整性方面特別有意義。

第四,在使用分組和排序子句進行資料檢索時,同樣可以顯著減少查詢中分組和排序的時間。

第五,通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的效能。

也許會有人要問:增加索引有如此多的優點,為什麼不對錶中的每乙個列建立乙個索引呢?因為,增加索引也有許多不利的方面。

第一,建立索引和維護索引要耗費時間,這種時間隨著資料量的增加而增加。

第二,索引需要佔物理空間,除了資料表佔資料空間之外,每乙個索引還要佔一定的物理空間,如果要建立聚簇索引,那麼需要的空間就會更大。

第三,當對表中的資料進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了資料的維護速度。

索引是建立在資料庫表中的某些列的上面。在建立索引的時候,應該考慮在哪些列上可以建立索引,在哪些列上不能建立索引。一般來說,應該在這些列上建立索引:在經常需要搜尋的列上,可以加快搜尋的速度;在作為主鍵的列上,強制該列的唯一性和組織表中資料的排列結構;在經常用在連線的列上,這些列主要是一些外來鍵,可以加快連線的速度;在經常需要根據範圍進行搜尋的列上建立索引,因為索引已經排序,其指定的範圍是連續的;在經常需要排序的列上建立索引,因為索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;在經常使用在where子句中的列上面建立索引,加快條件的判斷速度。

同樣,對於有些列不應該建立索引。一般來說,不應該建立索引的的這些列具有下列特點:

第一,對於那些在查詢中很少使用或者參考的列不應該建立索引。這是因為,既然這些列很少使用到,因此有索引或者無索引,並不能提高查詢速度。相反,由於增加了索引,反而降低了系統的維護速度和增大了空間需求。

第二,對於那些只有很少資料值的列也不應該增加索引。這是因為,由於這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的資料行佔了表中資料行的很大比例,即需要在表中搜尋的資料行的比例很大。增加索引,並不能明顯加快檢索速度。

第三,對於那些定義為text, image和bit資料型別的列不應該增加索引。這是因為,這些列的資料量要麼相當大,要麼取值很少。

第四,當修改效能遠遠大於檢索效能時,不應該建立索引。這是因為,修改效能和檢索效能是互相矛盾的。當增加索引時,會提高檢索效能,但是會降低修改效能。當減少索引時,會提高修改效能,降低檢索效能。因此,當修改效能遠遠大於檢索效能時,不應該建立索引。

我們先來看一下索引的分類,索引大致可按如下分類:

從資料結構角度

2、hash索引:

a. 僅僅能滿足"=",「in"和」<=>"查詢,不能使用範圍查詢

b. 其檢索效率非常高,索引的檢索可以一次定位,不像b-tree 索引需要從根節點到枝節點,最後才能訪問到頁節點這樣多次的io訪問,所以 hash 索引的查詢效率要遠高於 b-tree 索引

c. 只有memory儲存引擎顯示支援hash索引

從物理儲存角度

1、聚集索引(clustered index)

2、非聚集索引(non-clustered index)

從邏輯角度

1、普通索引或者單列索引

2、唯一索引

3、主鍵索引:主鍵索引是一種特殊的唯一索引,不允許有空值

4、多列索引(復合索引):復合索引指多個欄位上建立的索引,只有在查詢條件中使用了建立索引時的第乙個字段,索引才會被使用。使用復合索引時遵循最左字首集合

5、全文索引

在上文中,我們已經了解了資料結構及物理儲存角度,今天我們主要從邏輯角度來看看索引:

1、普通索引:這是最基本的索引型別,而且它沒有唯一性之類的限制。普通索引可以通過以下幾種方式建立:

建立索引,例如create index 《索引的名字》 on tablename (列的列表);

修改表,例如alter table tablename add index [索引的名字] (列的列表);

建立表的時候指定索引,例如create table tablename ( […], index [索引的名字] (列的列表) );

2、唯一索引:這種索引和前面的「普通索引」基本相同,但有乙個區別:索引列的所有值都只能出現一次,即必須唯一。唯一性索引可以用以下幾種方式建立:

建立索引,例如create unique index 《索引的名字》 on tablename (列的列表);

修改表,例如alter table tablename add unique [索引的名字] (列的列表);

建立表的時候指定索引,例如create table tablename ( […], unique [索引的名字] (列的列表) );

3、主鍵索引

主鍵是一種唯一性索引,但它必須指定為「primary key」。如果你曾經用過auto_increment型別的列,你可能已經熟悉主鍵之類的概念了。主鍵一般在建立表的時候指定,例如「create table tablename ( […], primary key (列的列表) ); 」。但是,我們也可以通過修改表的方式加入主鍵,例如「alter table tablename add primary key (列的列表); 」。每個表只能有乙個主鍵。

4、復合索引(組合索引、多列索引)

為了形象地對比單列索引和組合索引,為表新增多個字段:

create table mytable( id int not null, username varchar(16) not null, city varchar(50) not null, age int not null );

為了進一步榨取mysql的效率,就要考慮建立組合索引。就是將 name, city, age建到乙個索引裡:

alter table mytable add index name_city_age (name(10),city,age);

建表時,usernname長度為 16,這裡用 10。這是因為一般情況下名字的長度不會超過10,這樣會加速索引查詢速度,還會減少索引檔案的大小,提高insert的更新速度。

如果分別在 usernname,city,age上建立單列索引,讓該錶有3個單列索引,查詢時和上述的組合索引效率也會大不一樣,遠遠低於我們的組合索引。雖然此時有了三個索引,但mysql只能用到其中的那個它認為似乎是最有效率的單列索引。

建立這樣的組合索引,其實是相當於分別建立了下面三組組合mysql資料庫索引:

usernname,city,age  usernname,city  usernname 為什麼沒有 city,age這樣的組合索引呢?這是因為mysql組合索引「最左字首」的結果。簡單的理解就是只從最左面的開始組合。並不是只要包含這三列的查詢都會用到該組合索引,下面的幾個sql就會用到這個組合mysql資料庫索引:

select * from mytable whree username=「admin」 and city=「鄭州」

select * from mytable whree username=「admin」

而下面幾個則不會用到:

select * from mytable whree age=20 and city=「鄭州」 select * from mytable whree city=「鄭州」

關於最左字首的問題,我們會在後面討論到

5、全文索引

最左字首原則

mysql建立多列索引(聯合索引)有最左字首的原則,即最左優先,如:

如果有乙個2列的索引(col1,col2),則已經對(col1)、(col1,col2)上建立了索引;

如果有乙個3列索引(col1,col2,col3),則已經對(col1)、(col1,col2)、(col1,col2,col3)上建立了索引;

1、b+樹的資料項是復合的資料結構,比如(name,age,***)的時候,b+樹是按照從左到右的順序來建立搜尋樹的,比如當(張三,20,f)這樣的資料來檢索的時候,b+樹會優先比較name來確定下一步的所搜方向,如果name相同再依次比較age和***,最後得到檢索的資料;但當(20,f)這樣的沒有name的資料來的時候,b+樹就不知道第一步該查哪個節點,因為建立搜尋樹的時候name就是第乙個比較因子,必須要先根據name來搜尋才能知道下一步去**查詢。

2、比如當(張三,f)這樣的資料來檢索時,b+樹可以用name來指定搜尋方向,但下乙個欄位age的缺失,所以只能把名字等於張三的資料都找到,然後再匹配性別是f的資料了, 這個是非常重要的性質,即索引的最左匹配特性。(這種情況無法用到聯合索引)

關於最左字首的使用,有下面兩條說明:

最左字首匹配原則,非常重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。

=和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式

關於最左字首的例子,請參考:

什麼時候索引會失效

如果條件中有or,即使其中有條件帶索引也不會使用(這也是為什麼盡量少用or的原因)。注意:要想使用or,又想讓索引生效,只能將or條件中的每個列都加上索引

對於多列索引,不是使用的第一部分,則不會使用索引(即不符合最左字首原則)

like查詢是以%開頭

如果列型別是字串,那一定要在條件中將資料使用引號引用起來,否則不使用索引

如果mysql估計使用全表掃瞄要比使用索引快,則不使用索引

索引最左字首原則

今天在觀察慢sql統計的時候,發現了乙個sql的平均耗時長,而且總的掃瞄行數大,分析對應表的ddl,發現此表中只有乙個唯一索引index1 a,b,c 但是在查詢條件中沒有帶上a欄位,導致這個查詢sql沒有走索引,從而導致了全表掃瞄。這裡涉及到乙個索引最左字首原則,我們來一起看一下。下述摘自 通常我...

最左字首原則

當b 樹的資料項是復合的資料結構,比如 name,age,的時候,b 數是按照從左到右的順序來建立搜尋樹的,比如當 張三,20,f 這樣的資料來檢索的時候,b 樹會優先比較name來確定下一步的所搜方向,如果name相同再依次比較age和 最後得到檢索的資料 但當 20,f 這樣的沒有name的資料...

關於索引的最左字首原則

今天學習了下關於索引的最左字首的原理,小有成就感,在這裡做乙個學習記錄,以後學習的時候可以直接找出來複習。相信熟悉資料庫的大佬們跟索引達人們肯定都了解最索引的左字首原理,我在這裡還是再重複一下吧,文章還會結合實際例子來說明最左字首的原理。實驗工具 mysql 5.5 sqlyog 索引的最左字首原理...