浅析聚簇索引与非聚簇索引(也叫二级索引)
通俗點講
- 聚簇索引:將數(shù)據(jù)存儲與索引放到了一塊,找到索引也就找到了數(shù)據(jù)
- 非聚簇索引:將數(shù)據(jù)存儲于索引分開結(jié)構(gòu),索引結(jié)構(gòu)的葉子節(jié)點指向了數(shù)據(jù)的對應(yīng)行,myisam通過key_buffer把索引先緩存到內(nèi)存中,當(dāng)需要訪問數(shù)據(jù)時(通過索引訪問數(shù)據(jù)),在內(nèi)存中直接搜索索引,然后通過索引找到磁盤相應(yīng)數(shù)據(jù),這也就是為什么索引不在key buffer命中時,速度慢的原因
澄清一個概念:innodb中,在聚簇索引之上創(chuàng)建的索引稱之為輔助索引,輔助索引訪問數(shù)據(jù)總是需要二次查找,非聚簇索引都是輔助索引,像復(fù)合索引、前綴索引、唯一索引,輔助索引葉子節(jié)點存儲的不再是行的物理位置,而是主鍵值
何時使用聚簇索引與非聚簇索引
cluster.png
聚簇索引具有唯一性
由于聚簇索引是將數(shù)據(jù)跟索引結(jié)構(gòu)放到一塊,因此一個表僅有一個聚簇索引
一個誤區(qū):把主鍵自動設(shè)為聚簇索引
聚簇索引默認(rèn)是主鍵,如果表中沒有定義主鍵,InnoDB 會選擇一個唯一的非空索引代替。如果沒有這樣的索引,InnoDB 會隱式定義一個主鍵來作為聚簇索引。InnoDB 只聚集在同一個頁面中的記錄。包含相鄰健值的頁面可能相距甚遠(yuǎn)。如果你已經(jīng)設(shè)置了主鍵為聚簇索引,必須先刪除主鍵,然后添加我們想要的聚簇索引,最后恢復(fù)設(shè)置主鍵即可。
此時其他索引只能被定義為非聚簇索引。這個是最大的誤區(qū)。有的主鍵還是無意義的自動增量字段,那樣的話Clustered index對效率的幫助,完全被浪費(fèi)了。
剛才說到了,聚簇索引性能最好而且具有唯一性,所以非常珍貴,必須慎重設(shè)置。一般要根據(jù)這個表最常用的SQL查詢方式來進(jìn)行選擇,某個字段作為聚簇索引,或組合聚簇索引,這個要看實際情況。
記住我們的最終目的就是在相同結(jié)果集情況下,盡可能減少邏輯IO。
結(jié)合圖再仔細(xì)點看
image
image
MyISM使用的是非聚簇索引,非聚簇索引的兩棵B+樹看上去沒什么不同,節(jié)點的結(jié)構(gòu)完全一致只是存儲的內(nèi)容不同而已,主鍵索引B+樹的節(jié)點存儲了主鍵,輔助鍵索引B+樹存儲了輔助鍵。表數(shù)據(jù)存儲在獨(dú)立的地方,這兩顆B+樹的葉子節(jié)點都使用一個地址指向真正的表數(shù)據(jù),對于表數(shù)據(jù)來說,這兩個鍵沒有任何差別。由于索引樹是獨(dú)立的,通過輔助鍵檢索無需訪問主鍵的索引樹。
聚簇索引的優(yōu)勢
看上去聚簇索引的效率明顯要低于非聚簇索引,因為每次使用輔助索引檢索都要經(jīng)過兩次B+樹查找,這不是多此一舉嗎?聚簇索引的優(yōu)勢在哪?
聚簇索引的劣勢
image
所以建議使用int的auto_increment作為主鍵
image
主鍵的值是順序的,所以 InnoDB 把每一條記錄都存儲在上一條記錄的后面。當(dāng)達(dá)到頁的最大填充因子時(InnoDB 默認(rèn)的最大填充因子是頁大小的 15/16,留出部分空間用于以后修改),下一條記錄就會寫入新的頁中。一旦數(shù)據(jù)按照這種順序的方式加載,主鍵頁就會近似于被順序的記錄填滿(二級索引頁可能是不一樣的)
為什么主鍵通常建議使用自增id
聚簇索引的數(shù)據(jù)的物理存放順序與索引順序是一致的,即:只要索引是相鄰的,那么對應(yīng)的數(shù)據(jù)一定也是相鄰地存放在磁盤上的。如果主鍵不是自增id,那么可以想 象,它會干些什么,不斷地調(diào)整數(shù)據(jù)的物理地址、分頁,當(dāng)然也有其他一些措施來減少這些操作,但卻無法徹底避免。但,如果是自增的,那就簡單了,它只需要一 頁一頁地寫,索引結(jié)構(gòu)相對緊湊,磁盤碎片少,效率也高。
因為MyISAM的主索引并非聚簇索引,那么他的數(shù)據(jù)的物理地址必然是凌亂的,拿到這些物理地址,按照合適的算法進(jìn)行I/O讀取,于是開始不停的尋道不停的旋轉(zhuǎn)。聚簇索引則只需一次I/O。(強(qiáng)烈的對比)
不過,如果涉及到大數(shù)據(jù)量的排序、全表掃描、count之類的操作的話,還是MyISAM占優(yōu)勢些,因為索引所占空間小,這些操作是需要在內(nèi)存中完成的。
mysql中聚簇索引的設(shè)定
聚簇索引默認(rèn)是主鍵,如果表中沒有定義主鍵,InnoDB 會選擇一個唯一的非空索引代替。如果沒有這樣的索引,InnoDB 會隱式定義一個主鍵來作為聚簇索引。InnoDB 只聚集在同一個頁面中的記錄。包含相鄰健值的頁面可能相距甚遠(yuǎn)。
作者:kindol
鏈接:https://www.jianshu.com/p/fa8192853184
總結(jié)
以上是生活随笔為你收集整理的浅析聚簇索引与非聚簇索引(也叫二级索引)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SDK、API、JDK都是些什么?
- 下一篇: shell脚本获取系统的前一天日期,格式