sql中怎么實(shí)現(xiàn)聚集索引和非聚集索引

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)sql中怎么實(shí)現(xiàn)聚集索引和非聚集索引,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比井陘礦網(wǎng)站開(kāi)發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式井陘礦網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋井陘礦地區(qū)。費(fèi)用合理售后完善,十余年實(shí)體公司更值得信賴。

聚集索引

一種索引,該索引中鍵值的邏輯順序決定了表中相應(yīng)行的物理順序。

聚集索引確定表中數(shù)據(jù)的物理順序。聚集索引類似于電話簿,后者按姓氏排列數(shù)據(jù)。由于聚集索引規(guī)定數(shù)據(jù)在表中的物理存儲(chǔ)順序,因此一個(gè)表只能包含一個(gè)聚集索引。但該索引可以包含多個(gè)列(組合索引),就像電話簿按姓氏和名字進(jìn)行組織一樣。      聚集索引對(duì)于那些經(jīng)常要搜索范圍值的列特別有效。使用聚集索引找到包含第一個(gè)值的行后,便可以確保包含后續(xù)索引值的行在物理相鄰。例如,如果應(yīng)用程序執(zhí)行 的一個(gè)查詢經(jīng)常檢索某一日期范圍內(nèi)的記錄,則使用聚集索引可以迅速找到包含開(kāi)始日期的行,然后檢索表中所有相鄰的行,直到到達(dá)結(jié)束日期。這樣有助于提高此 類查詢的性能。同樣,如果對(duì)從表中檢索的數(shù)據(jù)進(jìn)行排序時(shí)經(jīng)常要用到某一列,則可以將該表在該列上聚集(物理排序),避免每次查詢?cè)摿袝r(shí)都進(jìn)行排序,從而節(jié) 省成本。      當(dāng)索引值唯一時(shí),使用聚集索引查找特定的行也很有效率。例如,使用唯一雇員 ID 列 emp_id 查找特定雇員的最快速的方法,是在 emp_id 列上創(chuàng)建聚集索引或 PRIMARY KEY 約束。

非聚集索引

一種索引,該索引中索引的邏輯順序與磁盤上行的物理存儲(chǔ)順序不同。

索引是通過(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ù)塊。如下圖:

(非聚集索引)

(聚集索引)

一、深入淺出理解索引結(jié)構(gòu)

實(shí)際上,您可以把索引理解為一種特殊的目錄。微軟的SQL SERVER提供了兩種索引:聚集索引(clustered index,也稱聚類索引、簇集索引)和非聚集索引(nonclustered index,也稱非聚類索引、非簇集索引)。下面,我們舉例來(lái)說(shuō)明一下聚集索引和非聚集索引的區(qū)別:   其實(shí),我們的漢語(yǔ)字典的正文本身就是一個(gè)聚集索引。比如,我們要查“安”字,就會(huì)很自然地翻開(kāi)字典的前幾頁(yè),因?yàn)椤鞍病钡钠匆羰恰癮n”,而按照拼音排序漢字的字典是以英文字母“a”開(kāi)頭并以“z”結(jié)尾的,那么“安”字就自然地排在字典的前部。如果您翻完了所有以“a”開(kāi)頭的部分仍然找不到這個(gè)字,那么就說(shuō)明您的字典中沒(méi)有這個(gè)字;同樣的,如果查“張”字,那您也會(huì)將您的字典翻到最后部分,因?yàn)椤皬垺钡钠匆羰恰皕hang”。也就是說(shuō),字典的正文部分本身就是一個(gè)目錄,您不需要再去查其他目錄來(lái)找到您需要找的內(nèi)容。我們把這種正文內(nèi)容本身就是一種按照一定規(guī)則排列的目錄稱為“聚集索引”。

如果您認(rèn)識(shí)某個(gè)字,您可以快速地從自動(dòng)中查到這個(gè)字。但您也可能會(huì)遇到您不認(rèn)識(shí)的字,不知道它的發(fā)音,這時(shí)候,您就不能按照剛才的方法找到您要查的字,而需要去根據(jù)“偏旁部首”查到您要找的字,然后根據(jù)這個(gè)字后的頁(yè)碼直接翻到某頁(yè)來(lái)找到您要找的字。但您結(jié)合“部首目錄”和“檢字表”而查到的字的排序并不是真正的正文的排序方法,比如您查“張”字,我們可以看到在查部首之后的檢字表中“張”的頁(yè)碼是672頁(yè),檢字表中“張”的上面是“馳”字,但頁(yè)碼卻是63頁(yè),“張”的下面是“弩”字,頁(yè)面是390頁(yè)。很顯然,這些字并不是真正的分別位于“張”字的上下方,現(xiàn)在您看到的連續(xù)的“馳、張、弩”三字實(shí)際上就是他們?cè)诜蔷奂饕械呐判?,是字典正文中的字在非聚集索引中的映射。我們可以通過(guò)這種方式來(lái)找到您所需要的字,但它需要兩個(gè)過(guò)程,先找到目錄中的結(jié)果,然后再翻到您所需要的頁(yè)碼。我們把這種目錄純粹是目錄,正文純粹是正文的排序方式稱為“非聚集索引”。

通過(guò)以上例子,我們可以理解到什么是“聚集索引”和“非聚集索引”。進(jìn)一步引申一下,我們可以很容易的理解:每個(gè)表只能有一個(gè)聚集索引,因?yàn)槟夸浿荒馨凑找环N方法進(jìn)行排序。

二、何時(shí)使用聚集索引或非聚集索引

下面的表總結(jié)了何時(shí)使用聚集索引或非聚集索引(很重要):

動(dòng)作描述      使用聚集索引      使用非聚集索引              列經(jīng)常被分組排序      應(yīng)      應(yīng)              返回某范圍內(nèi)的數(shù)據(jù)      應(yīng)      不應(yīng)              一個(gè)或極少不同值      不應(yīng)      不應(yīng)              小數(shù)目的不同值      應(yīng)      不應(yīng)              大數(shù)目的不同值      不應(yīng)      應(yīng)              頻繁更新的列      不應(yīng)      應(yīng)              外鍵列      應(yīng)      應(yīng)              主鍵列      應(yīng)      應(yīng)              頻繁修改索引列      不應(yīng)      應(yīng)

事實(shí)上,我們可以通過(guò)前面聚集索引和非聚集索引的定義的例子來(lái)理解上表。如:返回某范圍內(nèi)的數(shù)據(jù)一項(xiàng)。比如您的某個(gè)表有一個(gè)時(shí)間列,恰好您把聚合索引建立在了該列,這時(shí)您查詢2004年1月1日至2004年10月1日之間的全部數(shù)據(jù)時(shí),這個(gè)速度就將是很快的,因?yàn)槟倪@本字典正文是按日期進(jìn)行排序的,聚類索引只需要找到要檢索的所有數(shù)據(jù)中的開(kāi)頭和結(jié)尾數(shù)據(jù)即可;而不像非聚集索引,必須先查到目錄中查到每一項(xiàng)數(shù)據(jù)對(duì)應(yīng)的頁(yè)碼,然后再根據(jù)頁(yè)碼查到具體內(nèi)容。

三、結(jié)合實(shí)際,談索引使用的誤區(qū)

理論的目的是應(yīng)用。雖然我們剛才列出了何時(shí)應(yīng)使用聚集索引或非聚集索引,但在實(shí)踐中以上規(guī)則卻很容易被忽視或不能根據(jù)實(shí)際情況進(jìn)行綜合分析。下面我們將根據(jù)在實(shí)踐中遇到的實(shí)際問(wèn)題來(lái)談一下索引使用的誤區(qū),以便于大家掌握索引建立的方法。

1、主鍵就是聚集索引  這種想法筆者認(rèn)為是極端錯(cuò)誤的,是對(duì)聚集索引的一種浪費(fèi)。雖然SQL SERVER默認(rèn)是在主鍵上建立聚集索引的。   通常,我們會(huì)在每個(gè)表中都建立一個(gè)ID列,以區(qū)分每條數(shù)據(jù),并且這個(gè)ID列是自動(dòng)增大的,步長(zhǎng)一般為1。我們的這個(gè)辦公自動(dòng)化的實(shí)例中的列Gid就是如此。此時(shí),如果我們將這個(gè)列設(shè)為主鍵,SQL SERVER會(huì)將此列默認(rèn)為聚集索引。這樣做有好處,就是可以讓您的數(shù)據(jù)在數(shù)據(jù)庫(kù)中按照ID進(jìn)行物理排序,但筆者認(rèn)為這樣做意義不大。   顯而易見(jiàn),聚集索引的優(yōu)勢(shì)是很明顯的,而每個(gè)表中只能有一個(gè)聚集索引的規(guī)則,這使得聚集索引變得更加珍貴。   從我們前面談到的聚集索引的定義我們可以看出,使用聚集索引的最大好處就是能夠根據(jù)查詢要求,迅速縮小查詢范圍,避免全表掃描。在實(shí)際應(yīng)用中,因?yàn)?ID號(hào)是自動(dòng)生成的,我們并不知道每條記錄的ID號(hào),所以我們很難在實(shí)踐中用ID號(hào)來(lái)進(jìn)行查詢。這就使讓ID號(hào)這個(gè)主鍵作為聚集索引成為一種資源浪費(fèi)。其次,讓每個(gè)ID號(hào)都不同的字段作為聚集索引也不符合“大數(shù)目的不同值情況下不應(yīng)建立聚合索引”規(guī)則;當(dāng)然,這種情況只是針對(duì)用戶經(jīng)常修改記錄內(nèi)容,特別是索引項(xiàng)的時(shí)候會(huì)負(fù)作用,但對(duì)于查詢速度并沒(méi)有影響。   在辦公自動(dòng)化系統(tǒng)中,無(wú)論是系統(tǒng)首頁(yè)顯示的需要用戶簽收的文件、會(huì)議還是用戶進(jìn)行文件查詢等任何情況下進(jìn)行數(shù)據(jù)查詢都離不開(kāi)字段的是“日期”還有用戶本身的“用戶名”。   通常,辦公自動(dòng)化的首頁(yè)會(huì)顯示每個(gè)用戶尚未簽收的文件或會(huì)議。雖然我們的where語(yǔ)句可以僅僅限制當(dāng)前用戶尚未簽收的情況,但如果您的系統(tǒng)已建立了很長(zhǎng)時(shí)間,并且數(shù)據(jù)量很大,那么,每次每個(gè)用戶打開(kāi)首頁(yè)的時(shí)候都進(jìn)行一次全表掃描,這樣做意義是不大的,絕大多數(shù)的用戶1個(gè)月前的文件都已經(jīng)瀏覽過(guò)了,這樣做只能徒增數(shù)據(jù)庫(kù)的開(kāi)銷而已。事實(shí)上,我們完全可以讓用戶打開(kāi)系統(tǒng)首頁(yè)時(shí),數(shù)據(jù)庫(kù)僅僅查詢這個(gè)用戶近3個(gè)月來(lái)未閱覽的文件,通過(guò)“日期”這個(gè)字段來(lái)限制表掃描,提高查詢速度。如果您的辦公自動(dòng)化系統(tǒng)已經(jīng)建立的2年,那么您的首頁(yè)顯示速度理論上將是原來(lái)速度8倍,甚至更快。   在這里之所以提到“理論上”三字,是因?yàn)槿绻木奂饕€是盲目地建在ID這個(gè)主鍵上時(shí),您的查詢速度是沒(méi)有這么高的,即使您在“日期”這個(gè)字段上建立的索引(非聚合索引)。下面我們就來(lái)看一下在1000萬(wàn)條數(shù)據(jù)量的情況下各種查詢的速度表現(xiàn)(3個(gè)月內(nèi)的數(shù)據(jù)為25萬(wàn)條):

(1)僅在主鍵上建立聚集索引,并且不劃分時(shí)間段:

Select gid,fariqi,neibuyonghu,title from tgongwen

用時(shí):128470毫秒(即:128秒)

(2)在主鍵上建立聚集索引,在fariq上建立非聚集索引:

select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi> dateadd(day,-90,getdate())

用時(shí):53763毫秒(54秒)

(3)將聚合索引建立在日期列(fariqi)上:

select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi> dateadd(day,-90,getdate())

用時(shí):2423毫秒(2秒)

雖然每條語(yǔ)句提取出來(lái)的都是25萬(wàn)條數(shù)據(jù),各種情況的差異卻是巨大的,特別是將聚集索引建立在日期列時(shí)的差異。事實(shí)上,如果您的數(shù)據(jù)庫(kù)真的有1000 萬(wàn)容量的話,把主鍵建立在ID列上,就像以上的第1、2種情況,在網(wǎng)頁(yè)上的表現(xiàn)就是超時(shí),根本就無(wú)法顯示。這也是我摒棄ID列作為聚集索引的一個(gè)最重要的因素。得出以上速度的方法是:在各個(gè)select語(yǔ)句前加:

declare @d datetime set @d=getdate()

并在select語(yǔ)句后加:

select [語(yǔ)句執(zhí)行花費(fèi)時(shí)間(毫秒)]=datediff(ms,@d,getdate())

2、只要建立索引就能顯著提高查詢速度  事實(shí)上,我們可以發(fā)現(xiàn)上面的例子中,第2、3條語(yǔ)句完全相同,且建立索引的字段也相同;不同的僅是前者在fariqi字段上建立的是非聚合索引,后者在此字段上建立的是聚合索引,但查詢速度卻有著天壤之別。所以,并非是在任何字段上簡(jiǎn)單地建立索引就能提高查詢速度。   從建表的語(yǔ)句中,我們可以看到這個(gè)有著1000萬(wàn)數(shù)據(jù)的表中fariqi字段有5003個(gè)不同記錄。在此字段上建立聚合索引是再合適不過(guò)了。在現(xiàn)實(shí)中,我們每天都會(huì)發(fā)幾個(gè)文件,這幾個(gè)文件的發(fā)文日期就相同,這完全符合建立聚集索引要求的:“既不能絕大多數(shù)都相同,又不能只有極少數(shù)相同”的規(guī)則。由此看來(lái),我們建立“適當(dāng)”的聚合索引對(duì)于我們提高查詢速度是非常重要的。

3、把所有需要提高查詢速度的字段都加進(jìn)聚集索引,以提高查詢速度  上面已經(jīng)談到:在進(jìn)行數(shù)據(jù)查詢時(shí)都離不開(kāi)字段的是“日期”還有用戶本身的“用戶名”。既然這兩個(gè)字段都是如此的重要,我們可以把他們合并起來(lái),建立一個(gè)復(fù)合索引(compound index)。   很多人認(rèn)為只要把任何字段加進(jìn)聚集索引,就能提高查詢速度,也有人感到迷惑:如果把復(fù)合的聚集索引字段分開(kāi)查詢,那么查詢速度會(huì)減慢嗎?帶著這個(gè)問(wèn)題,我們來(lái)看一下以下的查詢速度(結(jié)果集都是25萬(wàn)條數(shù)據(jù)):(日期列fariqi首先排在復(fù)合聚集索引的起始列,用戶名neibuyonghu排在后列):

(1)select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi>''2004-5-5''

查詢速度:2513毫秒

(2)select gid,fariqi,neibuyonghu,title from Tgongwen             where fariqi>''2004-5-5'' and neibuyonghu=''辦公室''

查詢速度:2516毫秒

(3)select gid,fariqi,neibuyonghu,title from Tgongwen where neibuyonghu=''辦公室''

查詢速度:60280毫秒

從以上試驗(yàn)中,我們可以看到如果僅用聚集索引的起始列作為查詢條件和同時(shí)用到復(fù)合聚集索引的全部列的查詢速度是幾乎一樣的,甚至比用上全部的復(fù)合索引列還要略快(在查詢結(jié)果集數(shù)目一樣的情況下);而如果僅用復(fù)合聚集索引的非起始列作為查詢條件的話,這個(gè)索引是不起任何作用的。當(dāng)然,語(yǔ)句1、2的查詢速度一樣是因?yàn)椴樵兊臈l目數(shù)一樣,如果復(fù)合索引的所有列都用上,而且查詢結(jié)果少的話,這樣就會(huì)形成“索引覆蓋”,因而性能可以達(dá)到最優(yōu)。同時(shí),請(qǐng)記?。簾o(wú)論您是否經(jīng)常使用聚合索引的其他列,但其前導(dǎo)列一定要是使用最頻繁的列。

四、其他書上沒(méi)有的索引使用經(jīng)驗(yàn)總結(jié)

1、用聚合索引比用不是聚合索引的主鍵速度快  下面是實(shí)例語(yǔ)句:(都是提取25萬(wàn)條數(shù)據(jù))

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16''

使用時(shí)間:3326毫秒

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid<=250000

使用時(shí)間:4470毫秒

這里,用聚合索引比用不是聚合索引的主鍵速度快了近1/4。

2、用聚合索引比用一般的主鍵作order by時(shí)速度快,特別是在小數(shù)據(jù)量情況下

select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by fariqi

用時(shí):12936

select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by gid

用時(shí):18843

這里,用聚合索引比用一般的主鍵作order by時(shí),速度快了3/10。事實(shí)上,如果數(shù)據(jù)量很小的話,用聚集索引作為排序列要比使用非聚集索引速度快得明顯的多;而數(shù)據(jù)量如果很大的話,如10萬(wàn)以上,則二者的速度差別不明顯。

3、使用聚合索引內(nèi)的時(shí)間段,搜索時(shí)間會(huì)按數(shù)據(jù)占整個(gè)數(shù)據(jù)表的百分比成比例減少,而無(wú)論聚合索引使用了多少個(gè):

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>''2004-1-1''

用時(shí):6343毫秒(提取100萬(wàn)條)

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>''2004-6-6''

用時(shí):3170毫秒(提取50萬(wàn)條)

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16''

用時(shí):3326毫秒(和上句的結(jié)果一模一樣。如果采集的數(shù)量一樣,那么用大于號(hào)和等于號(hào)是一樣的)

select gid,fariqi,neibuyonghu,reader,title from Tgongwen             where fariqi>''2004-1-1'' and fariqi<''2004-6-6''

用時(shí):3280毫秒

4、日期列不會(huì)因?yàn)橛蟹置氲妮斎攵鴾p慢查詢速度  下面的例子中,共有100萬(wàn)條數(shù)據(jù),2004年1月1日以后的數(shù)據(jù)有50萬(wàn)條,但只有兩個(gè)不同的日期,日期精確到日;之前有數(shù)據(jù)50萬(wàn)條,有5000個(gè)不同的日期,日期精確到秒。

select gid,fariqi,neibuyonghu,reader,title from Tgongwen           where fariqi>''2004-1-1'' order by fariqi

用時(shí):6390毫秒

select gid,fariqi,neibuyonghu,reader,title from Tgongwen             where fariqi<''2004-1-1'' order by fariqi

用時(shí):6453毫秒

上述就是小編為大家分享的sql中怎么實(shí)現(xiàn)聚集索引和非聚集索引了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)頁(yè)名稱:sql中怎么實(shí)現(xiàn)聚集索引和非聚集索引
URL標(biāo)題:http://www.muchs.cn/article28/ihpsjp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制開(kāi)發(fā)、靜態(tài)網(wǎng)站、網(wǎng)站維護(hù)面包屑導(dǎo)航、網(wǎng)站導(dǎo)航網(wǎng)站內(nèi)鏈

廣告

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

外貿(mào)網(wǎng)站制作