亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

聚簇索引與非聚簇索引的區(qū)別

系統(tǒng) 1972 0

在《數(shù)據(jù)庫(kù)原理》里面,對(duì)聚簇索引的解釋是:聚簇索引的順序就是數(shù)據(jù)的物理存儲(chǔ)順序,而對(duì)非聚簇索引的解釋是:索引順序與數(shù)據(jù)物理排列順序無(wú)關(guān)。正式因?yàn)槿绱耍砸粋€(gè)表最多只能有一個(gè)聚簇索引。

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

聚簇索引與非聚簇索引的區(qū)別
非聚簇索引

聚簇索引與非聚簇索引的區(qū)別
聚簇索引


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

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

要建立一個(gè)聚簇索引,可以使用關(guān)鍵字CLUSTERED:CREATECLUSTEREDINDEXmycolumn_clust_indexONmytable(mycolumn)

要建立一個(gè)非聚簇索引CREATEINDEXmycolumn_indexONmytable(myclumn)

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

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


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

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

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

聚簇索引與非聚簇索引的區(qū)別

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

CREATE TABLE [ dbo ] . [ tabTest ] (
[ ID ] [ int ] IDENTITY ( 1 , 1 ) NOT 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 @i < 10000
begin
set @v = rand () * 1000
insert into tabTest( [ intValue ] ) values (@v)
set @i = @i + 1
end

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

聚簇索引與非聚簇索引的區(qū)別

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

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

聚簇索引與非聚簇索引的區(qū)別

SQL Server沒(méi)有使用任何索引,而是直接執(zhí)行了Table Scan,因?yàn)橹挥羞@樣,檢索效率才是最高的。


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

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

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

同樣一張表,如果我們?cè)趯?duì)應(yīng)字段上建立聚簇索引主鍵,由于聚簇索引的頁(yè)節(jié)點(diǎn)就是數(shù)據(jù)節(jié)點(diǎn),所以索引節(jié)點(diǎn)僅有8000個(gè),占用10個(gè)頁(yè)面,數(shù)據(jù)仍然占有1000個(gè)頁(yè)面。

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

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


結(jié)語(yǔ)

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

聚簇索引與非聚簇索引的區(qū)別


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 欧美成人亚洲国产精品 | 日日碰日日操 | 91成人免费福利网站在线 | 奇米第四色影视 | 性生活视频网址 | 亚洲欧美日韩中文v在线 | 五月婷婷视频在线 | 四虎一区 | 老司机午夜精品视频 | 久久草在线 | 羞羞的视频在线免费观看 | 精品国产成人高清在线 | 国产成在线人视频免费视频 | 黄页在线播放网址 | 国产一区二区不卡视频 | 国产精品永久免费10000 | 爱爱99| 久久精品国产一区二区三区不卡 | swag国产在线| 久久青青视频 | 精品玖玖玖视频在线观看 | 伊人狠狠丁香婷婷综合色 | 亚洲日本一区二区三区在线不卡 | 夜夜嘿视频免费看 | 国产福利第一视频 | 手机在线看片国产 | 乱人伦中文视频在线 | 四虎新网址| 97在线人人 | 欧美一级第一免费高清 | 奇米影视首页 | 欧美大片天天免费看视频 | 日本人一级毛片免费视频 | 欧美精品成人a多人在线观看 | 日韩欧美~中文字幕 | 国产乱人视频在线播放不卡 | 亚洲第五色综合网 | 久久福利青草精品资源站免费 | 国产精品一区二区四区 | 久久97视频| 色五月天天|