中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

數據庫的聚簇索引是什么

發布時間:2021-11-16 15:30:58 來源:億速云 閱讀:234 作者:iii 欄目:大數據

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

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

                                數據庫的聚簇索引是什么

                                                   圖-聚簇索引的數據分布

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

聚簇的數據有一些重要的優點:

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

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

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

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

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

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

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

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

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

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

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

InnoDB和MyISAM的數據分布對比

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

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命令做了優化。換句話說,數據在磁盤上的存儲方式已經最優,當行的順序是最優的,列col2的值是從1-100之間隨機賦值,所以有很多重復的值。

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

                                                數據庫的聚簇索引是什么

                                             圖-MyISAM表layout_test的數據分布

                           數據庫的聚簇索引是什么

                                                    圖-MyISAM表的主鍵分布

                            數據庫的聚簇索引是什么

                                                  圖-MyISAM表col2列索引的分布

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

                            數據庫的聚簇索引是什么

                                                    圖-InnoDB表的主鍵分布

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

                               數據庫的聚簇索引是什么    

                                                       圖-InnoDB的二級索引分布

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

                                數據庫的聚簇索引是什么

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

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

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

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

                                數據庫的聚簇索引是什么

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

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

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

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

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

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

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

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

                                數據庫的聚簇索引是什么

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

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

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

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

到此,關于“數據庫的聚簇索引是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

偃师市| 彭水| 公安县| 布尔津县| 宁津县| 阳新县| 河曲县| 永安市| 邢台市| 五峰| 庆云县| 都匀市| 禹州市| 万山特区| 徐州市| 若尔盖县| 葫芦岛市| 潮州市| 蒲城县| 朝阳县| 南康市| 永丰县| 焦作市| 鄂州市| 铜鼓县| 方正县| 闸北区| 宁河县| 咸阳市| 荔波县| 常德市| 诸暨市| 阿合奇县| 潞西市| 云梦县| 乐东| 沂源县| 阿坝县| 肥城市| 自治县| 常山县|