濮阳杆衣贸易有限公司

主頁 > 知識庫 > 數(shù)據(jù)庫中聚簇索引與非聚簇索引的區(qū)別[圖文]

數(shù)據(jù)庫中聚簇索引與非聚簇索引的區(qū)別[圖文]

熱門標簽:西安青牛防封電銷卡 400電話申請需要開戶費嗎 智能語音外呼系統(tǒng)哪個牌子好 溫州語音外呼系統(tǒng)代理 北京辦理400電話多少 南京電銷外呼系統(tǒng)運營商 威海智能語音外呼系統(tǒng) 山西語音外呼系統(tǒng)價格 重慶防封電銷機器人供應商

在《數(shù)據(jù)庫原理》里面,對聚簇索引的解釋是:聚簇索引的順序就是數(shù)據(jù)的物理存儲順序,而對非聚簇索引的解釋是:索引順序與數(shù)據(jù)物理排列順序無關(guān)。正式因為如此,所以一個表最多只能有一個聚簇索引。

不過這個定義太抽象了。在SQL Server中,索引是通過二叉樹的數(shù)據(jù)結(jié)構(gòu)來描述的,我們可以這么理解聚簇索引:索引的葉節(jié)點就是數(shù)據(jù)節(jié)點。而非聚簇索引的葉節(jié)點仍然是索引節(jié)點,只不過有一個指針指向?qū)臄?shù)據(jù)塊。如下圖:


非聚簇索引

 


聚簇索引


聚簇索引與非聚簇索引的本質(zhì)區(qū)別到底是什么?什么時候用聚簇索引,什么時候用非聚簇索引?

這是一個很復雜的問題,很難用三言兩語說清楚。我在這里從SQL Server索引優(yōu)化查詢的角度簡單談談(如果對這方面感興趣的話,可以讀一讀微軟出版的《Microsoft SQL Server 2000數(shù)據(jù)庫編程》第3單元的數(shù)據(jù)結(jié)構(gòu)引論以及第6、13、14單元)。


一、索引塊與數(shù)據(jù)塊的區(qū)別

大家都知道,索引可以提高檢索效率,因為它的二叉樹結(jié)構(gòu)以及占用空間小,所以訪問速度塊。讓我們來算一道數(shù)學題:如果表中的一條記錄在磁盤上占用 1000字節(jié)的話,我們對其中10字節(jié)的一個字段建立索引,那么該記錄對應的索引塊的大小只有10字節(jié)。我們知道,SQL Server的最小空間分配單元是“頁(Page)”,一個頁在磁盤上占用8K空間,那么這一個頁可以存儲上述記錄8條,但可以存儲索引800條?,F(xiàn)在我 們要從一個有8000條記錄的表中檢索符合某個條件的記錄,如果沒有索引的話,我們可能需要遍歷8000條×1000字節(jié)/8K字節(jié)=1000個頁面才能 夠找到結(jié)果。如果在檢索字段上有上述索引的話,那么我們可以在8000條×10字節(jié)/8K字節(jié)=10個頁面中就檢索到滿足條件的索引塊,然后根據(jù)索引塊上 的指針逐一找到結(jié)果數(shù)據(jù)塊,這樣IO訪問量要少的多。


二、索引優(yōu)化技術(shù)

是不是有索引就一定檢索的快呢?答案是否。有些時候用索引還不如不用索引快。比如說我們要檢索上述表中的所有記錄,如果不用索引,需要訪問8000 條×1000字節(jié)/8K字節(jié)=1000個頁面,如果使用索引的話,首先檢索索引,訪問8000條×10字節(jié)/8K字節(jié)=10個頁面得到索引檢索結(jié)果,再根 據(jù)索引檢索結(jié)果去對應數(shù)據(jù)頁面,由于是檢索所有數(shù)據(jù),所以需要再訪問8000條×1000字節(jié)/8K字節(jié)=1000個頁面將全部數(shù)據(jù)讀取出來,一共訪問了 1010個頁面,這顯然不如不用索引快。

SQL Server內(nèi)部有一套完整的數(shù)據(jù)檢索優(yōu)化技術(shù),在上述情況下,SQL Server的查詢計劃(Search Plan)會自動使用表掃描的方式檢索數(shù)據(jù)而不會使用任何索引。那么SQL Server是怎么知道什么時候用索引,什么時候不用索引的呢?SQL Server除了日常維護數(shù)據(jù)信息外,還維護著數(shù)據(jù)統(tǒng)計信息,下圖是數(shù)據(jù)庫屬性頁面的一個截圖:

從圖中我們可以看到,SQL Server自動維護統(tǒng)計信息,這些統(tǒng)計信息包括數(shù)據(jù)密度信息以及數(shù)據(jù)分布信息,這些信息幫助SQL Server決定如何制定查詢計劃以及查詢是是否使用索引以及使用什么樣的索引(這里就不再解釋它們到底如何幫助SQL Server建立查詢計劃的了)。我們還是來做個實驗。建立一張表:tabTest(ID, unqValue,intValue),其中ID是整形自動編號主索引,unqValue是uniqueidentifier類型,在上面建立普通索 引,intValue 是整形,不建立索引。之所以掛上一個沒有索引的intValue字段,就是防止SQL Server使用索引覆蓋查詢優(yōu)化技術(shù),這樣實驗就起不到作用了。向表中錄入10000條隨機記錄,代碼如下:

CREATE TABLE [dbo].[tabTest] (
 
[ID] [int] IDENTITY (11NOT NULL ,
 
[unqValue] [uniqueidentifier] NOT NULL ,
 
[intValue] [int] NOT NULL 
ON [PRIMARY]
GO

ALTER TABLE [dbo].[tabTest] WITH NOCHECK ADD 
 
CONSTRAINT [PK_tabTest] PRIMARY KEY  CLUSTERED 
 (
  
[ID]
 )  
ON [PRIMARY] 
GO

ALTER TABLE [dbo].[tabTest] ADD 
 
CONSTRAINT [DF_tabTest_unqValue] DEFAULT (newid()) FOR [unqValue]
GO

CREATE  INDEX [IX_tabTest_unqValue] ON [dbo].[tabTest]([unqValue]ON[PRIMARY]
GO

declare @i int
declare @v int

set @i=0
while @i10000
begin
    
set @v=rand()*1000    
    
insert into tabTest ([intValue]values (@v)
    
set @i=@i+1
end

然后我們執(zhí)行兩個查詢并查看執(zhí)行計劃,如圖:(在查詢分析器的查詢菜單中可以打開查詢計劃,同時圖上第一個查詢的GUID是我從數(shù)據(jù)庫中找的,大家做實驗的時候可以根據(jù)自己數(shù)據(jù)庫中的值來定):



從圖中可以看出,在第一個查詢中,SQL Server使用了IX_tabTest_unqValue索引,根據(jù)箭頭方向,計算機先在索引范圍內(nèi)找,找到后,使用Bookmark Lookup將索引節(jié)點映射到數(shù)據(jù)節(jié)點上,最后給出SELECT結(jié)果。在第二個查詢中,系統(tǒng)直接遍歷表給出結(jié)果,不過它使用了聚簇索引,為什么呢?不要忘 了,聚簇索引的頁節(jié)點就是數(shù)據(jù)節(jié)點!這樣使用聚簇索引會更快一些(不受數(shù)據(jù)刪除、更新留下的存儲空洞的影響,直接遍歷數(shù)據(jù)是要跳過這些空洞的)。

下面,我們在SQL Server中將ID字段的聚簇索引更改為非聚簇索引,然后再執(zhí)行select * from tabTest,這回我們看到的執(zhí)行計劃變成了:

SQL Server沒有使用任何索引,而是直接執(zhí)行了Table Scan,因為只有這樣,檢索效率才是最高的。


三、聚簇索引與非聚簇索引的本質(zhì)區(qū)別

現(xiàn)在可以討論聚簇索引與非聚簇索引的本質(zhì)區(qū)別了。正如本文最前面的兩個圖所示,聚簇索引的葉節(jié)點就是數(shù)據(jù)節(jié)點,而非聚簇索引的頁節(jié)點仍然是索引檢點,并保留一個鏈接指向?qū)獢?shù)據(jù)塊。

還是通過一道數(shù)學題來看看它們的區(qū)別吧:假設有一8000條記錄的表,表中每條記錄在磁盤上占用1000字節(jié),如果在一個10字節(jié)長的字段上建立非 聚簇索引主鍵,需要二叉樹節(jié)點16000個(這16000個節(jié)點中有8000個葉節(jié)點,每個頁節(jié)點都指向一個數(shù)據(jù)記錄),這樣數(shù)據(jù)將占用8000條 ×1000字節(jié)/8K字節(jié)=1000個頁面;索引將占用16000個節(jié)點×10字節(jié)/8K字節(jié)=20個頁面,共計1020個頁面。

同樣一張表,如果我們在對應字段上建立聚簇索引主鍵,由于聚簇索引的頁節(jié)點就是數(shù)據(jù)節(jié)點,所以索引節(jié)點僅有8000個,占用10個頁面,數(shù)據(jù)仍然占有1000個頁面。

下面我們看看在執(zhí)行插入操作時,非聚簇索引的主鍵為什么比聚簇索引主鍵要快。主鍵約束要求主鍵不能出現(xiàn)重復,那么SQL Server是怎么知道不出現(xiàn)重復的呢?唯一的方法就是檢索。對于非聚簇索引,只需要檢索20個頁面中的16000個節(jié)點就知道是否有重復,因為所有主鍵 鍵值在這16000個索引節(jié)點中都包含了。但對于聚簇索引,索引節(jié)點僅僅包含了8000個中間節(jié)點,至于會不會出現(xiàn)重復必須檢索另外1000個頁數(shù)據(jù)節(jié)點 才知道,那么相當于檢索10+1000=1010個頁面才知道是否有重復。所以聚簇索引主鍵的插入速度要比非聚簇索引主鍵的插入速度慢很多。

讓我們再來看看數(shù)據(jù)檢索的效率,如果對上述兩表進行檢索,在使用索引的情況下(有些時候SQL Server執(zhí)行計劃會選擇不使用索引,不過我們這里姑且假設一定使用索引),對于聚簇索引檢索,我們可能會訪問10個索引頁面外加1000個數(shù)據(jù)頁面得 到結(jié)果(實際情況要比這個好),而對于非聚簇索引,系統(tǒng)會從20個頁面中找到符合條件的節(jié)點,再映射到1000個數(shù)據(jù)頁面上(這也是最糟糕的情況),比較 一下,一個訪問了1010個頁面而另一個訪問了1020個頁面,可見檢索效率差異并不是很大。所以不管非聚簇索引也好還是聚簇索引也好,都適合排序,聚簇 索引僅僅比非聚簇索引快一點。


結(jié)語

好了,寫了半天,手都累了。關(guān)于聚簇索引與非聚簇索引效率問題的實驗就不做了,感興趣的話可以自己使用查詢分析器對查詢計劃進行分析。SQL Server是一個很復雜的系統(tǒng),尤其是索引以及查詢優(yōu)化技術(shù),Oracle就更復雜了。了解索引以及查詢背后的事情不是什么壞事,它可以幫助我們更為深 刻的了解我們的系統(tǒng)。

您可能感興趣的文章:
  • mysql聚簇索引的頁分裂原理實例分析
  • MySQL 索引的優(yōu)缺點以及創(chuàng)建索引的準則
  • MySQL btree索引與hash索引區(qū)別
  • MySQL 函數(shù)索引的優(yōu)化方案
  • Mysql索引性能優(yōu)化問題解決方案
  • 導致MySQL索引失效的一些常見寫法總結(jié)
  • 詳解MySQL 聚簇索引與非聚簇索引

標簽:濟寧 宜春 新余 河源 黃山 中衛(wèi) 金昌 貸款群呼

巨人網(wǎng)絡通訊聲明:本文標題《數(shù)據(jù)庫中聚簇索引與非聚簇索引的區(qū)別[圖文]》,本文關(guān)鍵詞  數(shù)據(jù)庫,中聚簇,索引,與,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡,涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《數(shù)據(jù)庫中聚簇索引與非聚簇索引的區(qū)別[圖文]》相關(guān)的同類信息!
  • 本頁收集關(guān)于數(shù)據(jù)庫中聚簇索引與非聚簇索引的區(qū)別[圖文]的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    栾川县| 曲阳县| 德昌县| 沁源县| 白沙| 宁国市| 察雅县| 吴堡县| 舞阳县| 渝北区| 读书| 孟州市| 扎鲁特旗| 基隆市| 灌南县| 金山区| 珠海市| 海阳市| 腾冲县| 宣武区| 海伦市| 南澳县| 甘孜县| 遵义市| 师宗县| 灵台县| 延边| 深水埗区| 榆林市| 锡林浩特市| 谢通门县| 盐源县| 蕲春县| 盐山县| 布尔津县| 芦山县| 龙游县| 太康县| 仙桃市| 陇西县| 长沙县|