索引這個詞在數(shù)據(jù)庫知識中耳熟能詳,是一種以空間換取時間的典型,索引結構往往能給數(shù)據(jù)操作帶來十分顯著的性能提升,我們都知道大多數(shù)的數(shù)據(jù)庫默認的索引結構都是B+樹,而聚集索引和非聚集索引(也叫輔助索引)都屬于B+樹結構;

所以首先我們簡單了解下B+樹:

B+樹:是一種高度平衡的為磁盤數(shù)據(jù)存取而設計的查找樹結構,所有的數(shù)據(jù)節(jié)點從左到右都是按順序存放在同一層的葉子節(jié)點上,這就為數(shù)據(jù)的順序查找或者范圍查找提供了極大的便利,查詢效率使用大O表示法為O(logN);

mysql使用B+樹存取數(shù)據(jù),相對于所有數(shù)據(jù)的順序查找來說,磁盤IO的速度相當?shù)拖?,而B+樹的查找往往只需要幾次的磁盤IO,效率是十分驚人的;

回到問題本身,聚集索引和非聚集索引的區(qū)別是什么?最根本的區(qū)別在于索引的順序和表數(shù)據(jù)的順序是否一致。。

①聚集索引:使用聚集索引的表,記錄和索引保持著一致的順序,這樣只要找到索引的值就能直接從葉子節(jié)點里面獲取到全部列數(shù)據(jù);

JAVA面試被問mysql聚集索引和非聚集索引的區(qū)別?

②非聚集索引:記錄和索引的順序往往不同,可理解為索引下面的葉子節(jié)點存儲的還是索引,想要獲得真正的列數(shù)據(jù),還需要再一次查詢;

JAVA面試被問mysql聚集索引和非聚集索引的區(qū)別?

根據(jù)上面的描述,聚集索引常常用在重復值不多(數(shù)據(jù)庫通常會自動加內(nèi)置的rowID保證列成為唯一索引),長度不大的列(比如主鍵等),而且聚集索引十分適合于順序查詢(order by)和范圍查詢(between,>,<),但是不適合于頻繁修改的列,和大字段的列,因為這會導致數(shù)據(jù)在磁盤上大量移動的性能消耗;

而非聚集索引更常被用于頻繁更新的列,列長度比較大的場景;

有人做過形象的比喻,聚集索引就像是使用拼音查字典(比如b就是100-150頁),而非聚集索引是使用部首查字典(比如弓在100頁,張在200頁)!

場景適用性截圖如下:

JAVA面試被問mysql聚集索引和非聚集索引的區(qū)別?

在下列場景中,不應該使用索引:

1,表數(shù)據(jù)不多:表數(shù)據(jù)不多的時候,磁盤IO本來就少,加索引只會增加IO開銷;

2,不常使用的列:沒必要;

3,頻繁更新的列:插入和刪除時需要額外維護一份索引數(shù)據(jù),會影響總的效率;