??mysql的索引策略中有一條是聚簇索引咬清,而聚簇索引并不是唯一索引捐凭,普通索引之類的索引類型记舆,而是一種數(shù)據(jù)的存儲(chǔ)方式鸽捻。大多數(shù)索引存在的形式為B-tree,葉子節(jié)點(diǎn)的索引則和其對(duì)應(yīng)的數(shù)據(jù)行數(shù)據(jù)緊湊的存儲(chǔ)在一起,這就是術(shù)語聚簇的含義御蒲。實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ)形式的是存儲(chǔ)引擎衣赶,但并不是所有存儲(chǔ)引擎都支持聚簇索引,而著名的InnoDB則是支持的引擎之一删咱,下面都以InnoDB為例屑埋。
-
聚簇索引的建立
??而存儲(chǔ)引擎不能管理兩份同樣的數(shù)據(jù),所以聚簇索引在同一張數(shù)據(jù)表中只能存在一個(gè)痰滋,其他的索引只能是非聚簇索引摘能,也就是二級(jí)索引。數(shù)據(jù)表的如果有指定primary key敲街,那么InnoDB就會(huì)把primary key作為聚簇索引來存儲(chǔ)团搞,如果沒有,則會(huì)取第一個(gè)not null多艇,unique的索引作為聚簇索引逻恐,unique的索引也不存在的話,InnoDB就會(huì)自行的峻黍,隱式的指定一個(gè)row ID列作為聚簇索引存儲(chǔ)复隆,但這個(gè)row ID不會(huì)被用戶管理。
-
聚簇索引的優(yōu)劣
聚簇索引一些重要的優(yōu)點(diǎn):
??1. 在有聚簇索引的數(shù)據(jù)表中姆涩,使用聚簇索引進(jìn)行查詢的時(shí)候挽拂,因?yàn)樗饕蛿?shù)據(jù)聚集在同一個(gè)B-tree中,能夠直接從索引獲取到數(shù)據(jù)行骨饿,比非聚簇索引的性能要好亏栈。
??2. 反之在沒有聚簇索引的數(shù)據(jù)表中,因?yàn)椴荒芡ㄟ^unique的值去聚集數(shù)據(jù)宏赘,所以需要通過非聚簇索引查詢數(shù)據(jù)的物理地址或者全表掃描來獲取數(shù)據(jù)绒北,這樣每一行數(shù)據(jù)可能都會(huì)導(dǎo)致一次磁盤I/O。
在提升性能的同時(shí)察署,聚簇索引也存在著缺點(diǎn):
??1. 更新聚簇索引的代價(jià)會(huì)很大闷游,因?yàn)樾枰獙?shù)據(jù)行和主鍵進(jìn)行重排,移動(dòng)到新的位置箕母,并且二級(jí)索引可能也需要更新储藐。
??2. 聚簇索引的插入速度嚴(yán)重依賴插入順序,嚴(yán)格的升序主鍵是性能最好的方式嘶是,但如果主鍵是亂序的插入,例如用uuid作為主鍵蛛碌,當(dāng)主鍵值需要插入到某一頁已經(jīng)寫滿的page中聂喇,存儲(chǔ)引擎就需要將page分裂成兩個(gè)頁面來容納數(shù)據(jù),這一個(gè)頁分裂(page split)
操作,page split會(huì)使得數(shù)據(jù)表占用更多的磁盤空間希太。
??3. 通過二級(jí)索引獲取需要兩次索引查找克饶,因?yàn)槎?jí)索引保存的是聚簇索引的主鍵,而不是指向數(shù)據(jù)的邏輯指針誊辉,所以獲取主鍵后需要再進(jìn)行一次搜索才能獲取數(shù)據(jù)矾湃。
-
聚簇索引和二級(jí)索引對(duì)比
??聚簇索引和二級(jí)索引的數(shù)據(jù)分布方式不同,在MyISAM和InnoDB的數(shù)據(jù)文件組織方式中也有體現(xiàn)堕澄。
??MyISAM的數(shù)據(jù)由3個(gè)文件組成:1. .frm(表結(jié)構(gòu)描述文件)
邀跃,2. .MYD(數(shù)據(jù)行文件)
,3. .MYI(索引文件)
蛙紫。
??InnoDB則有2個(gè)文件:1. .frm(表結(jié)構(gòu)描述文件)
拍屑,2. .MYD(數(shù)據(jù)行文件和索引信息)
。
??MyISAM引擎沒有使用索引和數(shù)據(jù)的聚集的分布方式坑傅,所以主鍵和其他索引的是沒有區(qū)別僵驰,就都存儲(chǔ)在索引文件中。
InnoDB的鎖機(jī)制是使用索引來實(shí)現(xiàn)唁毒,表現(xiàn)的等級(jí)為行級(jí)鎖蒜茴,而MyISAM則是表級(jí)鎖,這也跟數(shù)據(jù)分布方式有關(guān)浆西。InnoDB的主鍵索引與數(shù)據(jù)緊湊的聚集在一起粉私,并且包含了事務(wù)ID,用于事務(wù)MVCC的回滾指針室谚,而MyISAM則是數(shù)據(jù)與索引分離毡鉴,無法實(shí)現(xiàn)如此細(xì)粒度的鎖。
-
聚簇索引的注意事項(xiàng)
??1. InnoDB暫時(shí)不能由用戶選定索引作為聚簇索引秒赤,InnoDB有自己的聚簇索引選取規(guī)則猪瞬,所以在創(chuàng)建表的時(shí)候最好設(shè)置一個(gè)與業(yè)務(wù)無關(guān)的主鍵id作為聚簇索引,這樣修改二級(jí)索引和數(shù)據(jù)的時(shí)候入篮,無需移動(dòng)數(shù)據(jù)位置陈瘦,提升性能。
??2. 聚簇索引的主鍵id不要使用uuid潮售,uuid會(huì)使得數(shù)據(jù)的插入添加額外的頁分裂操作痊项,降低性能,最好使用單調(diào)自增的id酥诽。