數(shù)據(jù)庫的聚簇索引是什么

這篇文章主要介紹“數(shù)據(jù)庫的聚簇索引是什么”,在日常操作中,相信很多人在數(shù)據(jù)庫的聚簇索引是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”數(shù)據(jù)庫的聚簇索引是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

站在用戶的角度思考問題,與客戶深入溝通,找到夏邑網(wǎng)站設計與夏邑網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設計與互聯(lián)網(wǎng)技術結合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站設計、網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名注冊、虛擬空間、企業(yè)郵箱。業(yè)務覆蓋夏邑地區(qū)。

聚簇索引并不是一種單獨的索引類型,而是一種數(shù)據(jù)存儲方式。具體的細節(jié)依賴于其實現(xiàn)方式,但InnoDB的聚簇索引實際上在同一個結構中保存了B-Tree索引和數(shù)據(jù)行,即聚簇索引就是表。當表有聚簇索引時,它的數(shù)據(jù)行實際上存放在索引的葉子頁中,術語聚簇表示數(shù)據(jù)行和相鄰的鍵值緊湊地存儲在一起。因為無法同時把數(shù)據(jù)行存放在兩個不同的地方,所以一個表只能有一個聚簇索引。因為是存儲引擎負責實現(xiàn)索引,因此不是所有的存儲引擎都支持聚簇索引。如下圖為聚簇索引的數(shù)據(jù)分布,葉子頁包含了行的全部數(shù)據(jù),但是節(jié)點頁只包含了索引列。

                                數(shù)據(jù)庫的聚簇索引是什么

                                                   圖-聚簇索引的數(shù)據(jù)分布

InnoDB通過主鍵聚集數(shù)據(jù),如果沒有定義主鍵,InnoDB會選擇一個唯一的非空索引代替,如果沒有這樣的索引,InnoDB會隱式定義一個主鍵來作為聚簇索引。聚簇主鍵可能對性能有幫助,但也可能導致嚴重的性能問題。但是目前MySQL內(nèi)建的存儲引擎暫時不支持選擇哪個索引作為聚簇索引。

聚簇的數(shù)據(jù)有一些重要的優(yōu)點:

  • 可以將相關數(shù)據(jù)保存在一起,例如實現(xiàn)電子郵箱時,可以根據(jù)用戶id來聚集索引,這樣只需要從磁盤讀取少量的數(shù)據(jù)頁就能獲得某個用戶的全部郵件,如果沒有使用聚簇索引,則每封郵件都可能導致一次磁盤I/O;

  • 數(shù)據(jù)訪問更快。聚簇索引將索引和數(shù)據(jù)保存在同一個B-Tree中,因此從聚簇索引中獲取數(shù)據(jù)通常比在非聚簇索引中查找更快;

  • 使用覆蓋索引掃描的查詢可以直接使用頁節(jié)點中的主鍵值;

如果在設計表和查詢時能充分利用上面的優(yōu)點,那就能極大提升性能。同時聚簇索引也有一些缺點:

  • 聚簇索引最大限度地提高了I/O密集型應用的性能,但如果數(shù)據(jù)全部都放在內(nèi)存中,則訪問的順序就沒那么重要了,聚簇索引也就沒有什么優(yōu)勢了;

  • 插入速度嚴重依賴于插入順序。按照主鍵的方式順序插入是速度最快的方式。但如果不是按照主鍵順序加載數(shù)據(jù),那么在加載完成后最好用optimize table命令重新組織一下表;

  • 更新聚簇索引的代價很高,因為會強制InnoDB將每個被更新的行移到到新的位置;

  • 基于聚簇索引的表在插入新行,或者主鍵被更新導致需要移動行的時候,可能面臨頁分裂的問題。當行的主鍵值要求必須將這一行插入到某個已滿的頁中時,存儲引擎會將該頁分裂成兩個頁面來容納改行,這就是一次頁分裂的操作,頁分裂會導致表占用更多的磁盤空間;

  • 聚簇索引可能導致全表掃描變慢,尤其是行比較稀疏,或者由于頁分裂導致存儲不連續(xù)的時候;

  • 二級索引可能比想象的要更大,因為在二級索引的葉子節(jié)點包含了引用行的主鍵列;

  • 二級索引訪問需要兩次索引查找而不是一次,二級索引中保存的不是指向行的物理位置的指針,而是行的主鍵值,這意味著通過二級索引查找行,存儲引擎需要找到二級索引的葉子節(jié)點獲得對應的主鍵值,然后根據(jù)這個值去聚簇索引中查找對應的行,這里做了重復的工作:兩次B-Tree查找而不是一次。

InnoDB和MyISAM的數(shù)據(jù)分布對比

聚簇索引和非聚簇索引的數(shù)據(jù)分布有區(qū)別,以及對應的主鍵索引和二級索引的數(shù)據(jù)分布也有區(qū)別。以下表為例進行分析對比:

CREATE TABLE `test` (
  `id` int(11) NOT NULL,
  `last_name` char(30) NOT NULL,
  `first_name` char(30) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`last_name`,`first_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

假設改表的主鍵取值為1-10000,按照隨機的順序插入并使用optimize table命令做了優(yōu)化。換句話說,數(shù)據(jù)在磁盤上的存儲方式已經(jīng)最優(yōu),當行的順序是最優(yōu)的,列col2的值是從1-100之間隨機賦值,所以有很多重復的值。

MyISAM的數(shù)據(jù)分布非常簡單,按照數(shù)據(jù)插入的順序存儲在磁盤上,如下圖所示,從行的旁邊顯示了行號,從0開始遞增,因為行是定長的,所以MyISAM可以從表的開頭跳過所需的字節(jié)找到需要的行(MyISAM并不總是使用圖中的行號,而是根據(jù)定長還是變長的行使用不同的策略),這種分布方式很容易創(chuàng)建索引。下圖簡要顯示MyISAM的主鍵分布,只顯示了索引中的節(jié)點,索引中的每個葉子節(jié)點包含行號,col2列的索引和其它索引沒有區(qū)別,事實上MyISAM主鍵索引和其它索引在結構上沒有什么不同,主鍵索引就是一個名為PRIMARY的唯一非空索引。

                                                數(shù)據(jù)庫的聚簇索引是什么

                                             圖-MyISAM表layout_test的數(shù)據(jù)分布

                           數(shù)據(jù)庫的聚簇索引是什么

                                                    圖-MyISAM表的主鍵分布

                            數(shù)據(jù)庫的聚簇索引是什么

                                                  圖-MyISAM表col2列索引的分布

InnoDB的數(shù)據(jù)分布如下圖所示,因為InnoDB支持聚簇索引,所以使用不同的方式存儲相同的數(shù)據(jù),會注意到該圖顯示了整個表,而不是只有索引,事實上,在InnoDB中聚簇索引就是表,所以不像MyISAM那樣需要單獨的行存儲。聚簇索引的每個葉子節(jié)點都包含了主鍵值、事務ID、用于事務和MVCC的回滾指針以及所有的剩余列。如果主鍵是一個前綴索引,InnoDB也會包含完整的主鍵列和剩余的其它列。還有一點和MyISAM不同的是,InnoDB的二級索引和聚簇索引很不相同,InnoDB二級索引的葉子節(jié)點存儲的不是“行指針”而是主鍵值,并以此作為指向行的“指針”。這樣的策略減少了當出現(xiàn)行移動或者數(shù)據(jù)也分裂時二級索引的維護工作。使用主鍵值當作指針會讓二級索引占用更多的空間,換來的好處是InnoDB在移動行時無需更新二級索引中的這個“指針”。

                            數(shù)據(jù)庫的聚簇索引是什么

                                                    圖-InnoDB表的主鍵分布

下圖展示了InnoDB的二級索引結構,其中省略了一些細節(jié),InnoDB的非葉子節(jié)點包含了索引列和一個指向下級節(jié)點的指針(下級節(jié)點可以是非葉子節(jié)點,也可以是葉子節(jié)點),每個葉子節(jié)點都包含了索引列(這里是col2),緊接著是主鍵列(col1)。

                               數(shù)據(jù)庫的聚簇索引是什么    

                                                       圖-InnoDB的二級索引分布

下圖是InnoDB和MyISAM如何存儲表的抽象圖,可以很容易看出二者保存數(shù)據(jù)和索引的區(qū)別:

                                數(shù)據(jù)庫的聚簇索引是什么

                                                            圖-聚簇和非聚簇索引對比圖

可以看到InnoDB主索引是聚集索引,輔助索引是非聚集,存儲的是主鍵值。 MyISAM索引是非聚集索引,輔助索引和主索引都是存的數(shù)據(jù)行地址。

向聚簇索引插入順序的索引值

如果正在使用的InnoDB表沒有什么數(shù)據(jù)需要聚集,那么可以定義一個代理鍵作為主鍵,這種主鍵的數(shù)據(jù)應該和應用無關,最簡單的辦法就是使用自增列,這樣可以保證數(shù)據(jù)行是按順序?qū)懭?,對于根?jù)主鍵做關聯(lián)操作的性能也會更好。最好避免隨機的(不連續(xù)且值的分布范圍非常大)聚簇索引,特別是對于I/O密集型的應用,例如從性能的角度來看,使用UUID來作為聚簇索引則會很槽糕:它使得聚簇索引的插入變得完全隨機,這是最壞的情況,使得數(shù)據(jù)沒有任何的聚集特性??梢宰鰧Ρ仍囼?,自增id和UUID作為主鍵的性能對比,可以發(fā)現(xiàn)UUID主鍵插入行不僅花費的時間更長,而且索引占用的空間也更大,這樣一方面是由于主鍵字段更長,另一方面是由于頁分裂和碎片導致的。

                                數(shù)據(jù)庫的聚簇索引是什么

                                                        圖-向聚簇索引插入順序的索引值

如上圖所示,因為主鍵的值是順序的,所以InnoDB把每一條記錄都存儲在上一條記錄的后面。當達到頁的最大填充因子時,下一條記錄就會寫入新的頁中。一旦數(shù)據(jù)按照這種順序的方式加載,主鍵頁就會近似于被順序的記錄填滿,這也會是所期望的結果(然而二級索引頁可能是不一樣的)。

向聚簇索引中插入無序的值

對比一下使用UUID聚簇索引的表插入順序,因為新行的主鍵值不一定比之前插入的大,所以InnoDB無法簡單地總是把新行插入到索引的最后,而是需要為新的行尋找合適的位置-通常是已有數(shù)據(jù)的中間位置-并且分配空間,這會增加很多額外的工作,并導致數(shù)據(jù)分布不夠優(yōu)化。以下是總結的一些缺點:

  • 寫入的目標頁可能已經(jīng)刷入磁盤上并從緩存中移除,或者是還沒有被加載到緩存中,InnoDB在插入之前不得不先找到并從磁盤讀取目標頁到內(nèi)存中,這將導致大量的隨機I/O;

  • 因為寫入是亂序的,InnoDB不得不頻繁地做頁分裂操作,以便為新的行分配空間。頁分裂會導致移動大量數(shù)據(jù),一次插入最少需要修改三個頁而不是一個頁;

  • 由于頻繁的頁分裂,頁會變得稀疏并不被規(guī)則地填充,所以最終數(shù)據(jù)會有碎片

把這些隨機值載入到聚簇索引后,也許需要做一次optimize table來重建表并優(yōu)化頁的填充。

                                數(shù)據(jù)庫的聚簇索引是什么

                                                        圖-向聚簇索引中插入無序的值

從這個案例可以看出,使用InnoDB時應該盡可能地按主鍵順序插入數(shù)據(jù),并且盡可能地使用單調(diào)遞增的聚簇索引來載入新行。

順序的主鍵什么時候會造成更壞的結果?

對于高并發(fā)工作負載,在InnoDB中按主鍵順序插入可能會造成明顯的爭用。主鍵的上界會成為熱點,因為所有的插入都發(fā)送在這里,所以高并發(fā)插入可能導致間隙鎖競爭。另一個熱點是AUTO_INCREMENT鎖機制;如果遇到這個問題,則可以考慮重新設計表或者應用,或者更改innodb_autoinc_lock_mode配置。

到此,關于“數(shù)據(jù)庫的聚簇索引是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

網(wǎng)站標題:數(shù)據(jù)庫的聚簇索引是什么
文章起源:http://bm7419.com/article18/pscjdp.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供微信小程序、網(wǎng)站內(nèi)鏈、動態(tài)網(wǎng)站、網(wǎng)站改版網(wǎng)頁設計公司、外貿(mào)網(wǎng)站建設

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司