(一)SQLS如何訪問(wèn)沒有建立索引的數(shù)據(jù)表 Heap譯成漢語(yǔ)叫做“堆”,其本義暗含雜亂無(wú)章、無(wú)序的意思,前面提到數(shù)據(jù)值被寫進(jìn)數(shù)據(jù)頁(yè)時(shí),由于每一行記錄之間并沒有特定的排列順序,所以行與行 的順序就是隨機(jī)無(wú)序的,當(dāng)然表中的數(shù)據(jù)頁(yè)也就是無(wú)序的了,而表中所有數(shù)據(jù)頁(yè)就形成了“堆”??梢哉f(shuō),一張沒有索引的數(shù)據(jù)表,就像一個(gè)只有書柜而沒有索引卡 片柜的圖書館,書庫(kù)里面塞滿了一堆亂七八糟的圖書。當(dāng)讀者對(duì)管理員提交查詢請(qǐng)求后,管理員就一頭鉆進(jìn)書庫(kù),對(duì)照查找內(nèi)容從頭開始一架一柜的逐本查找。運(yùn)氣 好的話,在第一個(gè)書架的第一本書就 找到了,運(yùn)氣不好的話,要到最后一個(gè)書架的最后一本書才找到。 SQLS在接到查詢請(qǐng)求時(shí),首先會(huì)分析sysindexes表中一個(gè)叫做索引標(biāo)志符(INDID: Index ID)的字段的值,如果該值為0,表 示這是一張數(shù)據(jù)表而不是索引表,SQLS就會(huì)使用sysindexes表的另一個(gè)字段——也就是在前面提到過(guò)的FirstIAM值中找到該表的IAM頁(yè) 鏈,也就是所有數(shù)據(jù)頁(yè)集合。 這就是對(duì)一個(gè)沒有建立索引的數(shù)據(jù)表進(jìn)行數(shù)據(jù)查找的方式,是不是很沒效率?對(duì)于沒有索引的表,對(duì)于一“堆”這樣的記錄,SQLS也只能這樣做,而且更沒 勁的是,即使在第一行就找到了被查詢的記錄,SQLS仍然要從頭到尾的將表掃描一次。這種查詢稱為“遍歷”,又叫“表掃描”。 可見沒有建立索引的數(shù)據(jù)表照樣可以運(yùn)行,不過(guò)這種方法對(duì)于小規(guī)模的表來(lái)說(shuō)沒有什么太大的問(wèn)題,但要查詢海量的數(shù)據(jù)效率就太低了。 (二)SQLS如何訪問(wèn)建立了非聚集索引的數(shù)據(jù)表 如前所述,非聚集索引可以建多個(gè),具有B樹結(jié)構(gòu),其葉級(jí)節(jié)點(diǎn)不包含數(shù)據(jù)頁(yè),只包含索引行。假定一個(gè)表中只有非聚集索引,則每個(gè)索引行包含了非聚集索引 鍵值以及行定位符(ROW ID,RID),他們指向具有該鍵值的數(shù)據(jù)行,每一個(gè)RID由文件ID、頁(yè)編號(hào)和在頁(yè)中行的編號(hào)組成。 當(dāng)INDID的值在2至250之間時(shí),意味著表中存在非聚集索引頁(yè)。此時(shí),SQLS調(diào)用ROOT字段的值指向非聚集索引B樹的ROOT,在其中查找與 被查詢最相近的值,根據(jù)這個(gè)值找到在非葉級(jí)節(jié)點(diǎn)中的頁(yè)號(hào),然后順藤摸瓜,在葉級(jí)節(jié)點(diǎn)相應(yīng)的頁(yè)面中找到該值的RID,最后根據(jù)這個(gè)RID在Heap中定位所 在的頁(yè)和行并返回到查詢端。 例如:假定在Lastname上建立了非聚集索引,則執(zhí)行Select * From Member Where Lastname=’Ota’時(shí),查詢過(guò)程是: ①SQLS查詢INDID值為2; ?、诹⒓磸母霭l(fā),在非葉級(jí)節(jié)點(diǎn)中定位最接近Ota的值“Martin”,并查到其位于葉級(jí)頁(yè)面的第61頁(yè); ③僅在葉級(jí)頁(yè)面的第61頁(yè)的Martin下搜尋Ota的RID,其RID顯示為N∶706∶4,表示Lastname字段中名 為Ota的記錄位于堆的第706頁(yè)的第4行,N表示文件的ID值,與數(shù)據(jù)無(wú)關(guān); ?、芨鶕?jù)上述信息,SQLS立刻在堆的第706頁(yè)第4行將該記錄“揪”出來(lái)并顯示于前臺(tái)(客戶端)。視表的數(shù)據(jù)量大小,整個(gè)查詢過(guò)程費(fèi)時(shí)從百分之幾毫秒到數(shù)毫秒不等。 在談到索引基本概念的時(shí)候,我們就提到了這種方式:圖書館的前臺(tái)有很多索引卡片柜,里面分了若干的類別,諸如按照書名筆畫或拼音順序、作者筆畫或拼音順序等,但有兩點(diǎn)不同之處: ?、?nbsp;索引卡片上記錄了每本書擺放的具體位置——位于某柜某架的第幾本——而不是“特殊編號(hào)”; ?、?nbsp;書脊上并沒有那個(gè)“特殊編號(hào)”。管理員在索引柜中查到所需圖書的具體位置(RID)后,根據(jù)RID直接在書庫(kù)中的具體位置將書提出來(lái)。 顯然,這種查詢方式效率很高,但資源占用極大,因?yàn)闀鴰?kù)中書的位置隨時(shí)在發(fā)生變化,必然要求管理員花費(fèi)額外的精力和時(shí)間隨時(shí)做好索引更新。 (三)SQLS如何訪問(wèn)建立聚集索引的數(shù)據(jù)表 在聚集索引中,數(shù)據(jù)所在的數(shù)據(jù)頁(yè)是葉級(jí),索引數(shù)據(jù)所在的索引頁(yè)是非葉級(jí)。 查詢?cè)砗蜕鲜鰧?duì)非聚集索引的查詢相似,但由于記錄是按照聚集索引中索引鍵值進(jìn)行排序,換句話說(shuō),聚集索引的索引鍵值也就是具體的數(shù)據(jù)頁(yè)。 這就好比書庫(kù)中的書就是按照書名的拼音在排序,而且也只按照這一種排序方式建立相應(yīng)的索引卡片,于是查詢起來(lái)要比上述只建立非聚集索引的方式要簡(jiǎn)單得多。仍以上面的查詢?yōu)槔? 假定在Lastname字段上建立了聚集索引,則執(zhí)行Select * From Member Where Lastname=’Ota’時(shí),查詢過(guò)程是: ①SQLS查詢INDID值為1,這是在系統(tǒng)中只建立了聚集索引的標(biāo)志; ?、诹⒓磸母霭l(fā),在非葉級(jí)節(jié)點(diǎn)中定位最接近Ota的值“Martin”,并查到其位于葉級(jí)頁(yè)面的第120頁(yè); ?、墼谖挥谌~級(jí)頁(yè)面第120頁(yè)的Martin下搜尋到Ota條目,而這一條目已是數(shù)據(jù)記錄本身; ?、軐⒃撚涗浄祷乜蛻舳?。 這一次的效率比第二種方法更高,以致于看起來(lái)更美,然而它最大的優(yōu)點(diǎn)也恰好是它最大的缺點(diǎn)——由于同一張表中同時(shí)只能按照一種順序排列,所以在任何一 種數(shù)據(jù)表中的聚集索引只能建立一個(gè);并且建立聚集索引需要至少相當(dāng)于源表120%的附加空間,以存放源表的副本和索引中間頁(yè)。 難道魚和熊掌就不能兼顧了嗎?辦法是有的。 (四)SQLS如何訪問(wèn)既有聚集索引、又有非聚集索引的數(shù)據(jù)表 如果我們?cè)诮⒎蔷奂饕跋冉⒘司奂饕脑挘敲捶蔷奂饕涂梢允褂镁奂饕年P(guān)鍵字進(jìn)行檢索。就像在圖書館中,前臺(tái)卡片柜中可以有不同類 別的圖書索引卡,然而每張卡片上都載明了那個(gè)特殊編號(hào)——并不是書籍存放的具體位置。這樣在最大程度上既照顧了數(shù)據(jù)檢索的快捷性,又使索引的日常維護(hù)變得 更加可行,這是最為科學(xué)的檢索方法。 也就是說(shuō),在只建立了非聚集索引的情況下,每個(gè)葉級(jí)節(jié)點(diǎn)指明了記錄的行定位符(RID);而在既有聚集索引又有非聚集索引的情況下,每個(gè)葉級(jí)節(jié)點(diǎn)所指向的是該聚集索引的索引鍵值,即數(shù)據(jù)記錄本身。 假設(shè)聚集索引建立在Lastname上,而非聚集索引建立在Firstname上,當(dāng)執(zhí)行Select * From Member Where Firstname=’Mike’時(shí),查詢過(guò)程是: ?、賁QLS查詢INDID值為2; ②立即從根出發(fā),在Firstname的非聚集索引的非葉級(jí)節(jié)點(diǎn)中定位最接近Mike的值“Jose”條目; ?、蹚腏ose條目下的葉級(jí)頁(yè)面中查到Mike邏輯位置——不是RID而是聚集索引的指針; ?、芨鶕?jù)這一指針?biāo)甘疚恢?,直接進(jìn)入位于Lastname的聚集索引中的葉級(jí)頁(yè)面中到達(dá)Mike數(shù)據(jù)記錄本身; ?、輰⒃撚涗浄祷乜蛻舳?。 這就完全和我們?cè)?#8220;索引的基本概念”中講到的現(xiàn)實(shí)場(chǎng)景完全一樣了,當(dāng)數(shù)據(jù)發(fā)生更新的時(shí)候,SQLS只負(fù)責(zé)對(duì)聚集索引的鍵值加以維護(hù),而不必考慮非聚集 索引。只要我們?cè)贗D類的字段上建立聚集索引,而在其它經(jīng)常需要查詢的字段上建立非聚集索引,通過(guò)這種科學(xué)的、有針對(duì)性的在一張表上分別建立聚集索引和非 聚集索引的方法,我們既享受了索引帶來(lái)的靈活與快捷,又相對(duì)避免了維護(hù)索引所導(dǎo)致的大量的額外資源消耗。 索引的優(yōu)點(diǎn)和不足 索引有一些先天不足 1、系統(tǒng)要占用大約為表的1.2倍的硬盤和內(nèi)存空間來(lái)保存索引; 2、更新數(shù)據(jù)的時(shí)候,系統(tǒng)必須要有額外的時(shí)間來(lái)同時(shí)對(duì)索引進(jìn)行更新,以維持?jǐn)?shù)據(jù)和索引的一致性。 當(dāng)然建立索引的優(yōu)點(diǎn)也是顯而易見的,在海量數(shù)據(jù)的情況下,如果合理的建立了索引,則會(huì)大大加強(qiáng)SQLS執(zhí)行查詢、對(duì)結(jié)果進(jìn)行排序、分組的操作效率。 實(shí)踐表明,不恰當(dāng)?shù)乃饕坏谑聼o(wú)補(bǔ),反而會(huì)降低系統(tǒng)性能。因?yàn)榇罅康乃饕谶M(jìn)行插入、修改和刪除操作時(shí)比沒有索引要花費(fèi)更多的系統(tǒng)時(shí)間。 在如下字段建立索引應(yīng)該是不恰當(dāng)?shù)模? 1、很少或從不引用的字段; 2、邏輯型的字段,如男或女(是或否)等。 綜上所述,提高查詢效率是以消耗一定的系統(tǒng)資源為代價(jià)的,索引不能盲目的建立,必須要有統(tǒng)籌的規(guī)劃,一定要在“加快查詢速度”與“降低修改速度”之間做好平衡。有得必有失,此消則彼長(zhǎng),這是考驗(yàn)一個(gè)DBA是否優(yōu)秀的很重要的指標(biāo) 建立索引時(shí)一定要在“加快查詢速度”與“降低修改速度”之間做好平衡,有得必有失,此消則彼長(zhǎng)。那么,SQLS維護(hù)索引時(shí)究竟怎樣消耗資源?應(yīng)該從哪些方面對(duì)索引進(jìn)行管理與優(yōu)化?以下從六個(gè)方面來(lái)回答這些問(wèn)題。 一.頁(yè)分裂 微軟MOC教導(dǎo)我們:當(dāng)一個(gè)數(shù)據(jù)頁(yè)達(dá)到了8K容量,如果此時(shí)發(fā)生插入或更新數(shù)據(jù)的操作,將導(dǎo)致頁(yè)的分裂(又名頁(yè)拆分): 1.有聚集索引的情況下:聚集索引將被插入和更新的行指向特定的頁(yè),該頁(yè)由聚集索引關(guān)鍵字決定; 2.只有堆的情況下:只要有空間就可以插入新的行,但是如果我們對(duì)行數(shù)據(jù)的更新需要更多的空間,以致大于當(dāng)前頁(yè)的可用空間,行就被移到新的頁(yè)中,并且在原位置留下一個(gè)轉(zhuǎn)發(fā)指針,指向被移動(dòng)的新行,如果具有轉(zhuǎn)發(fā)指針的行又被移動(dòng)了,那么原來(lái)的指針將重新指向新的位置; 3.如果堆中有非聚集索引,那么盡管插入和更新操作在堆中不會(huì)發(fā)生頁(yè)分裂,但是在非聚集索引上仍然產(chǎn)生頁(yè)分裂。 無(wú)論有無(wú)索引,大約一半的數(shù)據(jù)將保留在老頁(yè)面,而另一半將放入新頁(yè)面,并且新頁(yè)面可能被分配到任何可用的頁(yè)。所以,頻繁頁(yè)分裂,后果很嚴(yán)重,將使物理表產(chǎn)生大量數(shù)據(jù)碎片,導(dǎo)致直接造成I/O效率的急劇下降,最后,不得不停止SQLS的運(yùn)行并重建索引。 二.填充因子 然而在“混沌之初”,就可以在一定程度上避免不愉快出現(xiàn),在創(chuàng)建索引時(shí),可以為這個(gè)索引指定一個(gè)填充因子,以便在索引的每個(gè)葉級(jí)頁(yè)面上保留一定百分比的空 間,將來(lái)數(shù)據(jù)可以進(jìn)行擴(kuò)充和減少頁(yè)分裂。填充因子是從0到100的百分比數(shù)值,設(shè)為100時(shí)表示將數(shù)據(jù)頁(yè)填滿,只有當(dāng)不會(huì)對(duì)數(shù)據(jù)進(jìn)行更改時(shí)(例如只讀表 中)才用此設(shè)置。值越小則數(shù)據(jù)頁(yè)上的空閑空間越大,這樣可以減少在索引增長(zhǎng)過(guò)程中進(jìn)行頁(yè)分裂的需要,但這一操作需要占用更多的硬盤空間。 填充因子只在創(chuàng)建索引時(shí)執(zhí)行,索引創(chuàng)建以后,當(dāng)表中進(jìn)行數(shù)據(jù)的添加、刪除或更新時(shí),是不會(huì)保持填充因子的,如果想在數(shù)據(jù)頁(yè)上保持額外的空間,則有悖于使用 填充因子的本意,因?yàn)殡S著數(shù)據(jù)的輸入,SQLS必須在每個(gè)頁(yè)上進(jìn)行頁(yè)拆分,以保持填充因子指定的空閑空間。因此,只有在表中的數(shù)據(jù)進(jìn)行了較大的變動(dòng),才可 以填充數(shù)據(jù)頁(yè)的空閑空間。這時(shí),可以從容的重建索引,重新指定填充因子,重新分布數(shù)據(jù)。 反之,填充因子指定不當(dāng),就會(huì)降低數(shù)據(jù)庫(kù)的讀取性能,其降低量與填充因子設(shè)置值成反比。例如,當(dāng)填充因子的值為50時(shí),數(shù)據(jù)庫(kù)的讀取性能會(huì)降低兩倍。所以,只有在表中根據(jù)現(xiàn)有數(shù)據(jù)創(chuàng)建新索引,并且可以預(yù)見將來(lái)會(huì)對(duì)這些數(shù)據(jù)進(jìn)行哪些更改時(shí),設(shè)置填充因子才有意義。 三.兩道數(shù)學(xué)題 假定數(shù)據(jù)庫(kù)設(shè)計(jì)沒有問(wèn)題,那么是否像上篇分析的那樣,當(dāng)你建立了眾多的索引,在查詢工作中SQLS就只能按照“最高指示”用索引處理每一個(gè)提交的查詢呢?答案是否定的。 實(shí)際上,SQLS幾乎完全是“自主”的決定是否使用索引或使用哪一個(gè)索引。 這是怎么回事呢? 讓我們先來(lái)算一道題:如果某表的一條記錄在磁盤上占用1000字節(jié)(1K)的話,我們對(duì)其中10字節(jié)的一個(gè)字段建立索引,那么該記錄對(duì)應(yīng)的索引大小只有 10字節(jié)(0.01K)。上篇說(shuō)過(guò),SQLS的最小空間分配單元是“頁(yè)(Page)”,一個(gè)頁(yè)面在磁盤上占用8K空間,所以一頁(yè)只能存儲(chǔ)8條“記錄”,但 可以存儲(chǔ)800條“索引”?,F(xiàn)在我們要從一個(gè)有8000條記錄的表中檢索符合某個(gè)條件的記錄(有Where子句),如果沒有索引的話,我們需要遍歷 8000條×1000字節(jié)/8K字節(jié)=1000個(gè)頁(yè)面才能夠找到結(jié)果。如果在檢索字段上有上述索引的話,那么我們可以在8000條×10字節(jié)/8K字節(jié)= 10個(gè)頁(yè)面中就檢索到滿足條件的索引塊,然后根據(jù)索引塊上的指針逐一找到結(jié)果數(shù)據(jù)塊,這樣I/O訪問(wèn)量肯定要少得多。 然而有時(shí)用索引比不用索引還快。 同上,如果要無(wú)條件檢索全部記錄(不用Where子句),不用索引的話,需要訪問(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è)面,這顯然不如不用索引快。 SQLS內(nèi)部有一套完整的數(shù)據(jù)索引優(yōu)化技術(shù),在上述情況下,SQLS會(huì)自動(dòng)使用表掃描的方式檢索數(shù)據(jù)而不會(huì)使用任何索引。那么SQLS是怎么知道什么時(shí)候用索引,什么時(shí)候不用索引的呢?因?yàn)镾QLS除了維護(hù)數(shù)據(jù)信息外,還維護(hù)著數(shù)據(jù)統(tǒng)計(jì)信息。 四.統(tǒng)計(jì)信息 打開企業(yè)管理器,單擊“Database”節(jié)點(diǎn),右擊Northwind數(shù)據(jù)庫(kù)→單擊“屬性”→選擇“Options”選項(xiàng)卡,觀察“Settings”下的各項(xiàng)復(fù)選項(xiàng),你發(fā)現(xiàn)了什么? 從Settings中我們可以看到,在數(shù)據(jù)庫(kù)中,SQLS將默認(rèn)的自動(dòng)創(chuàng)建和更新統(tǒng)計(jì)信息,這些統(tǒng)計(jì)信息包括數(shù)據(jù)密度和分布信息,正是它們幫助SQLS確定最佳的查詢策略:建立查詢計(jì)劃和是否使用索引以及使用什么樣的索引。 在創(chuàng)建索引時(shí),SQLS會(huì)創(chuàng)建分布數(shù)據(jù)頁(yè)來(lái)存放有關(guān)索引的兩種統(tǒng)計(jì)信息:分布表和密度表。查詢優(yōu)化器使用這些統(tǒng)計(jì)信息估算使用該索引進(jìn)行查詢的成本(Cost),并在此基礎(chǔ)上判斷該索引對(duì)某個(gè)特定查詢是否有用。 隨著表中的數(shù)據(jù)發(fā)生變化,SQLS自動(dòng)定期更新這些統(tǒng)計(jì)信息。采樣是在各個(gè)數(shù)據(jù)頁(yè)上隨機(jī)進(jìn)行。從磁盤讀取一個(gè)數(shù)據(jù)頁(yè)后,該數(shù)據(jù)頁(yè)上的所有行都被用來(lái)更新統(tǒng) 計(jì)信息。統(tǒng)計(jì)信息更新的頻率取決于字段或索引中的數(shù)據(jù)量以及數(shù)據(jù)更改量。比如,對(duì)于有一萬(wàn)條記錄的表,當(dāng)1000個(gè)索引鍵值發(fā)生改變時(shí),該表的統(tǒng)計(jì)信息便 可能需要更新,因?yàn)?000 個(gè)值在該表中占了10%,這是一個(gè)很大的比例。而對(duì)于有1千萬(wàn)條記錄的表來(lái)說(shuō),1000個(gè)索引值發(fā)生更改的意義則可以忽略不 計(jì),因此統(tǒng)計(jì)信息就不會(huì)自動(dòng)更新。 五.索引的人工維護(hù) 上面講到,某些不合適的索引將影響到SQLS的性能,隨著應(yīng)用系統(tǒng)的運(yùn)行,數(shù)據(jù)不斷地發(fā)生變化,當(dāng)數(shù)據(jù)變化達(dá)到某一個(gè)程度時(shí)將會(huì)影響到索引的使用。這時(shí)需要用戶自己來(lái)維護(hù)索引。 隨著數(shù)據(jù)行的插入、刪除和數(shù)據(jù)頁(yè)的分裂,有些索引頁(yè)可能只包含幾頁(yè)數(shù)據(jù),另外應(yīng)用在執(zhí)行大量I/O的時(shí)候,重建非聚聚集索引可以維護(hù)I/O的效率。重建索引實(shí)質(zhì)上是重新組織B樹。需要重建索引的情況有: 1.?dāng)?shù)據(jù)和使用模式大幅度變化; 2.排序的順序發(fā)生改變; 3.要進(jìn)行大量插入操作或已經(jīng)完成; 4.使用I/O查詢的磁盤讀次數(shù)比預(yù)料的要多; 5.由于大量數(shù)據(jù)修改,使得數(shù)據(jù)頁(yè)和索引頁(yè)沒有充分使用而導(dǎo)致空間的使用超出估算; 6.dbcc檢查出索引有問(wèn)題。 六.索引的使用原則 接近尾聲的時(shí)候,讓我們?cè)購(gòu)牧硪粋€(gè)角度認(rèn)識(shí)索引的兩個(gè)重要屬性----惟一性索引和復(fù)合性索引。 惟一性索引保證在索引列中的全部數(shù)據(jù)是惟一的,不會(huì)包含冗余數(shù)據(jù)。如果表中已經(jīng)有一個(gè)主鍵約束或者惟一性約束,那么當(dāng)創(chuàng)建表或者修改表時(shí),SQLS自動(dòng)創(chuàng)建一個(gè)惟一性索引。但出于必須保證惟一性,那么應(yīng)該創(chuàng)建主鍵約束或者惟一性鍵約束,而不是創(chuàng)建一個(gè)惟一性索引。 復(fù)合索引就是一個(gè)索引創(chuàng)建在兩個(gè)列或者多個(gè)列上。在搜索時(shí),當(dāng)兩個(gè)或者多個(gè)列作為一個(gè)關(guān)鍵值時(shí),最好在這些列上創(chuàng)建復(fù)合索引。當(dāng)創(chuàng)建復(fù)合索引時(shí),應(yīng)該考慮 這些規(guī)則:最多可以把16個(gè)列合并成一個(gè)單獨(dú)的復(fù)合索引,構(gòu)成復(fù)合索引的列的總長(zhǎng)度不能超過(guò)900字節(jié);在復(fù)合索引中,所有的列必須來(lái)自同一個(gè)表中,不能 跨表建立復(fù)合列;在復(fù)合索引中,列的排列順序是非常重要的,原則上,應(yīng)該首先定義最惟一的列,例如在(COL1,COL2)上的索引與在(COL2, COL1)上的索引是不相同的,因?yàn)閮蓚€(gè)索引的列的順序不同;為了使查詢優(yōu)化器使用復(fù)合索引,查詢語(yǔ)句中的WHERE子句必須參考復(fù)合索引中第一個(gè)列。 綜上所述,我們總結(jié)了如下索引使用原則: 1.邏輯主鍵使用惟一的成組索引,對(duì)系統(tǒng)鍵(作為存儲(chǔ)過(guò)程)采用惟一的非成組索引,對(duì)任何外鍵列采用非成組索引。考慮數(shù)據(jù)庫(kù)的空間有多大,表如何進(jìn)行訪問(wèn),還有這些訪問(wèn)是否主要用作讀寫; 2.不要索引memo/note 字段,不要索引大型字段(有很多字符),這樣作會(huì)讓索引占用太多的存儲(chǔ)空間; 3.不要索引常用的小型表; 4.一般不要為小型數(shù)據(jù)表設(shè)置過(guò)多的索引,如果經(jīng)常有插入和刪除操作就更不要設(shè)置索引,因?yàn)镾QLS對(duì)插入和刪除操作提供的索引維護(hù)可能比掃描表空間消耗的時(shí)間更多。 查詢是一個(gè)物理過(guò)程,表面上是SQLS在東跑西跑,其實(shí)真正大部分壓馬路的工作是由磁盤輸入輸出系統(tǒng)(I/O)完成,全表掃描需要從磁盤上讀表的每一個(gè)數(shù) 據(jù)頁(yè),如果有索引指向數(shù)據(jù)值,則I/O讀幾次磁盤就可以了。但是,在隨時(shí)發(fā)生的增、刪、改操作中,索引的存在會(huì)大大增加工作量,因此,合理的索引設(shè)計(jì)是建 立在對(duì)各種查詢的分析和預(yù)測(cè)上的,只有正確地使索引與程序結(jié)合起來(lái),才能產(chǎn)生最佳的優(yōu)化方案。 SQLS是一個(gè)很復(fù)雜的系統(tǒng),讓索引以及查詢背后的東西真相大白,可以幫助我們更為深刻的了解我們的系統(tǒng)。一句話,索引就像鹽,少則無(wú)味多則咸。 |
|
來(lái)自: ShangShujie > 《data base》