索引機制、索引技術、索引設計準則

1.橫向比較數據庫中不同的索引機制

一、引言

對數據庫索引的關注從未淡出我的們的討論,那麼數據庫索引是什麼樣的?聚集索引與非聚集索引有什麼不同?希望本文對各位同仁有一定的幫助。有不少存疑的地方,誠心希望各位不吝賜教指正,共同進步。

二、B-Tree

我們常見的數據庫系統,其索引使用的數據結構多是B-Tree或者B+Tree。例如,MsSql使用的是B+TreeOracleSysbase使用的是B-Tree。所以在最開始,簡單地介紹一下B-Tree

B-Tree不同於Binary Tree(二叉樹,最多有兩個子樹),一棵M階的B-Tree滿足以下條件:

1)每個結點至多有M個孩子;

2)除根結點和葉結點外,其它每個結點至少有M/2個孩子;

3)根結點至少有兩個孩子(除非該樹僅包含一個結點)

4)所有葉結點在同一層,葉結點不包含任何關鍵字信息;

5)K個關鍵字的非葉結點恰好包含K+1個孩子;

另外,對於一個結點,其內部的關鍵字是從小到大排序的。以下是B-TreeM=4)的樣例:

對於每個結點,主要包含一個關鍵字數組Key[],一個指針數組(指向兒子)Son[]。在B-Tree內,查找的流程是:使用順序查找(數組長度較短時)或折半查找方法查找Key[]數組,若找到關鍵字K,則返回該結點的地址及KKey[]中的位置;否則,可確定K在某個Key[i]Key[i+1]之間,則從Son[i]所指的子結點繼續查找,直到在某結點中查找成功;或直至找到葉結點且葉結點中的查找仍不成功時,查找過程失敗。

接着,我們使用以下圖片演示如何生成B-TreeM=4,依次插入1~6)
從圖可見,當我們插入關鍵字4時,由於原結點已經滿了,故進行分裂,基本按一半的原則進行分裂,然後取出中間的關鍵字2,升級(這裏是成爲根結點)。其它的依類推,就是這樣一個大概的過程。

三、數據庫索引

1.什麼是索引

在數據庫中,索引的含義與日常意義上的索引一詞並無多大區別(想想小時候查字典),它是用於提高數據庫表數據訪問速度的數據庫對象。

A)索引可以避免全表掃描。多數查詢可以僅掃描少量索引頁及數據頁,而不是遍歷所有數據頁。

B)對於非聚集索引,有些查詢甚至可以不訪問數據頁。

C)聚集索引可以避免數據插入操作集中於表的最後一個數據頁。

D)一些情況下,索引還可用於避免排序操作。

當然,衆所周知,雖然索引可以提高查詢速度,但是它們也會導致數據庫系統更新數據的性能下降,因爲大部分數據更新需要同時更新索引。

2.索引的存儲

一條索引記錄中包含的基本信息包括:鍵值(即你定義索引時指定的所有字段的值)+邏輯指針(指向數據頁或者另一索引頁)

當你爲一張空表創建索引時,數據庫系統將爲你分配一個索引頁,該索引頁在你插入數據前一直是空的。此頁此時既是根結點,也是葉結點。每當你往表中插入一行數據,數據庫系統即向此根結點中插入一行索引記錄。當根結點滿時,數據庫系統大抵按以下步驟進行分裂:

A)創建兩個兒子結點

B)將原根結點中的數據近似地拆成兩半,分別寫入新的兩個兒子結點

C)根結點中加上指向兩個兒子結點的指針

通常狀況下,由於索引記錄僅包含索引字段值(以及4-9字節的指針),索引實體比真實的數據行要小許多,索引頁相較數據頁來說要密集許多。一個索引頁可以存儲數量更多的索引記錄,這意味着在索引中查找時在I/O上佔很大的優勢,理解這一點有助於從本質上了解使用索引的優勢。

3.索引的類型

A)聚集索引,表數據按照索引的順序來存儲的。對於聚集索引,葉子結點即存儲了真實的數據行,不再有另外單獨的數據頁。

B)非聚集索引,表數據存儲順序與索引順序無關。對於非聚集索引,葉結點包含索引字段值及指向數據頁數據行的邏輯指針,該層緊鄰數據頁,其行數量與數據錶行數據量一致。


在一張表上只能創建一個聚集索引,因爲真實數據的物理順序只可能是一種。如果一張表沒有聚集索引,那麼它被稱爲堆集Heap)。這樣的表中的數據行沒有特定的順序,所有的新行將被添加的表的末尾位置。

4.聚集索引

在聚集索引中,葉結點也即數據結點,所有數據行的存儲順序與索引的存儲順序一致。

1)聚集索引與查詢操作

如上圖,我們在名字字段上建立聚集索引,當需要在根據此字段查找特定的記錄時,數據庫系統會根據特定的系統表查找的此索引的根,然後根據指針查找下一個,直到找到。例如我們要查詢“Green”,由於它介於[Bennet,Karsen],據此我們找到了索引頁1007,在該頁中“Green”介於[Greane, Hunter]間,據此我們找到葉結點1133(也即數據結點),並最終在此頁中找以了目標數據行。

此次查詢的IO包括3個索引頁的查詢(其中最後一次實際上是在數據頁中查詢)。這裏的查找可能是從磁盤讀取(Physical Read)或是從緩存中讀取(Logical Read),如果此表訪問頻率較高,那麼索引樹中較高層的索引很可能在緩存中被找到。所以真正的IO可能小於上面的情況。

2)聚集索引與插入操作

最簡單的情況下,插入操作根據索引找到對應的數據頁,然後通過挪動已有的記錄爲新數據騰出空間,最後插入數據。

如果數據頁已滿,則需要拆分數據頁(頁拆分是一種耗費資源的操作,一般數據庫系統中會有相應的機制要儘量減少頁拆分的次數,通常是通過爲每頁預留空間來實現)

A)在該使用的數據段(extent)上分配新的數據頁,如果數據段已滿,則需要分配新段。

B)調整索引指針,這需要將相應的索引頁讀入內存並加鎖。

C)大約有一半的數據行被歸入新的數據頁中。

D)如果表還有非聚集索引,則需要更新這些索引指向新的數據頁。

特殊情況

A)如果新插入的一條記錄包含很大的數據,可能會分配兩個新數據頁,其中之一用來存儲新記錄,另一存儲從原頁中拆分出來的數據。

B)通常數據庫系統中會將重複的數據記錄存儲於相同的頁中。

C)類似於自增列爲聚集索引的,數據庫系統可能並不拆分數據頁,頁只是簡單的新添數據頁。

3)聚集索引與刪除操作

刪除行將導致其下方的數據行向上移動以填充刪除記錄造成的空白。

如果刪除的行是該數據頁中的最後一行,那麼該數據頁將被回收,相應的索引頁中的記錄將被刪除。如果回收的數據頁位於跟該表的其它數據頁相同的段上,那麼它可能在隨後的時間內被利用。如果該數據頁是該段的唯一一個數據頁,則該段也被回收。

對於數據的刪除操作,可能導致索引頁中僅有一條記錄,這時,該記錄可能會被移至鄰近的索引頁中,原索引頁將被回收,即所謂的索引合併

5.非聚集索引

非聚集索引與聚集索引相比:

A)葉子結點並非數據結點

B)葉子結點爲每一真正的數據行存儲一個-指針

C)葉子結點中還存儲了一個指針偏移量,根據頁指針及指針偏移量可以定位到具體的數據行。

D)類似的,在除葉結點外的其它索引結點,存儲的也是類似的內容,只不過它是指向下一級的索引頁的。

聚集索引是一種稀疏索引,數據頁上一級的索引頁存儲的是頁指針,而不是行指針。而對於非聚集索引,則是密集索引,在數據頁的上一級索引頁它爲每一個數據行存儲一條索引記錄。

對於根與中間級的索引記錄,它的結構包括:

A)索引字段值

B)RowId(即對應數據頁的頁指針+指針偏移量)。在高層的索引頁中包含RowId是爲了當索引允許重複值時,當更改數據時精確定位數據行。

C)下一級索引頁的指針

對於葉子層的索引對象,它的結構包括:

A)索引字段值

B)RowId

1)非聚集索引與查詢操作

針對上圖,如果我們同樣查找“Green”,那麼一次查詢操作將包含以下IO3個索引頁的讀取+1個數據頁的讀取。同樣,由於緩存的關係,真實的IO實際可能要小於上面列出的。

2)非聚集索引與插入操作

如果一張表包含一個非聚集索引但沒有聚集索引,則新的數據將被插入到最末一個數據頁中,然後非聚集索引將被更新。如果也包含聚集索引,該聚集索引將被用於查找新行將要處於什麼位置,隨後,聚集索引、以及非聚集索引將被更新。

3)非聚集索引與刪除操作

如果在刪除命令的Where子句中包含的列上,建有非聚集索引,那麼該非聚集索引將被用於查找數據行的位置,數據刪除之後,位於索引葉子上的對應記錄也將被刪除。如果該表上有其它非聚集索引,則它們葉子結點上的相應數據也要刪除。

如果刪除的數據是該數所頁中的唯一一條,則該頁也被回收,同時需要更新各個索引樹上的指針。

由於沒有自動的合併功能,如果應用程序中有頻繁的隨機刪除操作,最後可能導致表包含多個數據頁,但每個頁中只有少量數據。

6.索引覆蓋

索引覆蓋是這樣一種索引策略:當某一查詢中包含的所需字段皆包含於一個索引中,此時索引將大大提高查詢性能。

包含多個字段的索引,稱爲複合索引。索引最多可以包含31個字段,索引記錄最大長度爲600B。如果你在若干個字段上創建了一個複合的非聚集索引,且你的查詢中所需Select字段及Where,Order By,Group By,Having子句中所涉及的字段都包含在索引中,則只搜索索引頁即可滿足查詢,而不需要訪問數據頁。由於非聚集索引的葉結點包含所有數據行中的索引列值,使用這些結點即可返回真正的數據,這種情況稱之爲索引覆蓋

在索引覆蓋的情況下,包含兩種索引掃描:

A)匹配索引掃描

B)非匹配索引掃描

1)匹配索引掃描

此類索引掃描可以讓我們省去訪問數據頁的步驟,當查詢僅返回一行數據時,性能提高是有限的,但在範圍查詢的情況下,性能提高將隨結果集數量的增長而增長。

針對此類掃描,索引必須包含查詢中涉及的的所有字段,另外,還需要滿足:Where子句中包含索引中的引導列Leading Column),例如一個複合索引包含A,B,C,D四列,則A引導列。如果Where子句中所包含列是BCD或者BD等情況,則只能使用非匹配索引掃描。

2)非配置索引掃描

正如上述,如果Where子句中不包含索引的導引列,那麼將使用非配置索引掃描。這最終導致掃描索引樹上的所有葉子結點,當然,它的性能通常仍強於掃描所有的數據頁。

 

2.關係數據庫的索引技術

摘 要:索引是影響關係數據庫(RDBMS)性能的重要因素之一。當今常用的關係數據庫,如SQL Server、Sybase、Oracle、DB2等,爲了提高性能,都提供相應的索引機制。本文以微軟的SQL Server數據庫爲例,介紹索引的概念、使用方法以及日常維護。

關鍵詞:數據庫、索引、檢索

索引的概念

索引是一個單獨的、物理的數據庫結構,它是某個表中一列或若干列值的集合和相應的指向表中物理標識這些值的數據頁的邏輯指針清單。表的存儲由兩部分組成,一部分用來存放數據頁面,另一部分存放索引頁面。通常,索引頁面相對於數據頁面來說小得多。數據檢索花費的大部分開銷是磁盤讀寫,沒有索引就需要從磁盤上讀表的每一個數據頁,如果有索引,則只需查找索引頁面就可以了。所以建立合理的索引,就能加速數據的檢索過程。

SQL Server採用B-樹結構的索引,根據索引的順序與數據表的物理順序是否相同可以分爲:聚簇索引(clustered index)和非聚簇索引(nonclustered index)。

(1)聚簇索引重新組織表中的數據以按指定的一個或多個列的值排序。聚簇索引的葉節點包含實際的數據,因此用它查找數據很快,但每個表只能建一個聚簇索引。

(2)非聚簇索引不重新組織表中的數據,它的葉節點中存儲了組成非聚簇索引的列的值和行定位指針。一個表可以建249 個非聚簇索引。

通俗的說,漢語字典的正文就是一個建立在拼音基礎上的聚簇索引,以英文字母“a”開頭並以“z”結尾。比如,我們要查“阿”字,就會翻開字典的第一頁,因爲“阿”的拼音是“a”,所以排在字典的前面。如果您翻完了所有以“a”開頭的部分仍然找不到這個字,那麼就說明字典中沒有這個字。同樣的,如果查“做”字,就會把字典翻到最後。

字典的“偏旁部首”是非聚簇索引。比如我們要查“阿”字,在查部首之後,看到部首檢字表中“阿”的頁碼是1頁,“阿”的上面是“際”字,但頁碼卻是277頁,“阿”的下面是“隴”字,頁碼是416頁。很顯然,這些字並不是真正的分別位於“阿”字的上下方,現在看到的連續的“際、阿、隴”三字實際上就是他們在非聚簇索引中的排序,是字典正文中的字在非聚簇索引中的映射。

索引的使用

1)聚簇索引的使用

在聚簇索引下,數據在物理上按順序排在數據頁上,重複值也排在一起,因而在那些包含範圍檢查(between、<、<=、>、>=)或使用group by、order by的查詢時,一旦找到具有範圍中第一個鍵值的行,具有後續索引值的行必然連在一起,不必進一步搜索,避免了大範圍掃描,可以大大提高查詢速度。

聚簇索引的侯選列是:

u        經常按範圍存取的列,如date>”20050101” and date< “20050131”;

u        經常在where子句中使用並且插入是隨機的主鍵列;

u        在group by或order by中使用的列;

u        在連接操作中使用的列。

2)非聚簇索引的使用

由於非聚簇索引的葉級點不包含實際的數據,因此它檢索效率較低,但一個表只能建一個聚簇索引,當用戶需要建立多個索引時就需要使用非聚簇索引了。在建立非聚簇索引時,要權衡索引對查詢速度的加快與降低修改速度之間的利弊。

在下面情況中使用非聚簇索引:

u        常用於集合函數(如Sum,....)的列;

u        常用於join, order by, group by的列;

u        查尋出的數據不超過表中數據量的20%。

表1  索引使用情況分析表

情況描述

使用聚簇索引

使用非聚簇索引

用於返回某範圍內數據的列

不應

經常被用作分組排序的列

小數目不同值的列

不應

連接操作使用的列

頻繁更新、修改的列

不應

一個或極少不同值的列

不應

不應

大數目不同值的列

不應

3)創建索引需要注意的要點

1)    慎重選擇作爲聚簇索引的列

默認情況下,SQL Server用主鍵創建聚簇索引。這種做法常常造成聚簇索引的浪費。通常,我們會爲每個表建立一個ID列,以區分每條數據,並且該列是自動增大的,步長一般爲1。如果我們把這個列設爲主鍵,SQL Server會將此列默認爲聚簇索引。這樣做可以使數據在數據庫中按ID進行物理排序,但這種做法在實際應用中意義並不大。根據前面談到的聚簇索引的定義和使用情況可以看出,使用聚簇索引的最大好處就是能夠根據查詢要求,迅速返回某個範圍內的數據,避免全表掃描。在實際應用中,因爲ID號是自動生成的,我們並不知道每條記錄的ID號,所以我們不太可能用ID號來進行查詢。這就使聚簇索引成爲擺設,造成資源浪費。其次,讓每個值都不同的ID列作爲聚簇索引也不符合“大數目的不同值情況下不應建立聚簇索引”規則。

一般情況下,數據庫應用系統進行數據檢索都離不開“ 用戶名(代碼)”、“日期”字段。以筆者所用的HIS系統(醫院管理信息系統)爲例,我們進行費用、處方、檢查單等信息檢索時需要根據“住院號”和“日期”這兩個字段來返回特定範圍內的數據。下面我們分幾種情況觀察在不同索引條件下查詢相同內容所用的時間。

假設病人費用表名爲“brfy”,其中住院號字段名爲“zyh”,日期字段名爲“riqi”,要求是從表brfy中檢索zyh爲“028246”的病人2005年3月1日到20日的費用,對應的SQL語句如下:

Select * from brfy where zyh=’028246’ and riqi>=’20050301’ and riqi<=’20050320’;

第一種情況,用ID列建立聚簇索引,不爲zyh和riqi建立索引,查詢時間爲87秒。

第二種情況,用ID列建立聚簇索引,爲zyh和riqi兩列建立非聚簇索引(zyh在前),查詢時間爲33秒。

第三種情況,用zyh和riqi兩列建立聚簇索引(zyh在前),查詢時間爲2秒。

由以上分析可以看出聚簇索引是非常寶貴的,應該爲經常用於檢索某個範圍內數據的列或group by、order by等子句的列建立聚簇索引,這樣能夠極大的提高系統性能。

2)    重視以多個列創建的索引中列的順序問題

一些用戶認爲只要合理的選擇列建立索引,不必關心列的順序就可以提高檢索速度,這種觀點是錯誤的。多列索引中列的先後順序應該和實際應用中where、group by或order by等子句裏列的放置位置相同。參考上面舉的例子,在第二、第三種情況下,如果把riqi放在zyh前面,執行上述SQL語句就不會用到這兩個索引,檢索的時間也會變得很長。

索引的維護

數據庫系統運行一段時間後,隨着數據行的插入、刪除和數據頁的分裂,索引對系統的優化性能就會大大降低。這時候,我們需要對索引進行分析和重建。

SQL Server使用DBCC SHOWCONTIG確定是否需要重建表的索引。在 SQL Server的查詢分析器中輸入命令:

Use database_name

Declare @table_id int

Set @table_id=object_id ('Employee')

Dbcc showcontig (@table_id)

在命令返回的參數中Scan Density 是索引性能的關鍵指示器,這個值越接近100%越好,一般在低於90%的情況下,就需要重建索引。重建索引可以使用DBCC DBREINDEX,使用方式如下:

dbcc dbreindex('表名', 索引名, 填充因子)       /*填充因子一般爲90或100*/

如果重建後,Scan Density還沒有達到100%,可以重建該表的所有索引:

dbcc dbreindex('表名', '', 填充因子)

在良好的數據庫設計基礎上,有效地使用索引是數據庫應用系統取得高性能的基礎。然而,任何事物都具有兩面性,索引也不例外。索引的建立需要佔用額外的存儲空間,並且在增、刪、改操作中也會增加一定的工作量,因此,在適當的地方增加適當的索引並從不合理的地方刪除次要的索引,將有助於優化那些性能較差的數據庫應用系統。實踐表明,合理的索引設計是建立在對各種查詢的分析和預測上的,只有正確地使索引與程序結合起來,才能產生最佳的優化方案

 

3.淺談數據庫索引

數據庫索引是爲了增加查詢速度而對錶字段附加的一種標識。見過很多人機械的理解索引的概念,認爲增加索引只有好處沒有壞處。這裏想把之前的索引學習筆記總結一下:

    首先明白爲什麼索引會增加速度,DB在執行一條Sql語句的時候,默認的方式是根據搜索條件進行全表掃描,遇到匹配條件的就加入搜索結果集合。如果我們對某一字段增加索引,查詢時就會先去索引列表中一次定位到特定值的行數,大大減少遍歷匹配的行數,所以能明顯增加查詢的速度。那麼在任何時候都應該加索引麼?這裏有幾個反例:1、如果每次都需要取到所有表記錄,無論如何都必須進行全表掃描了,那麼是否加索引也沒有意義了。2、對非唯一的字段,例如“性別”這種大量重複值的字段,增加索引也沒有什麼意義。3、對於記錄比較少的表,增加索引不會帶來速度的優化反而浪費了存儲空間,因爲索引是需要存儲空間的,而且有個致命缺點是對於update/insert/delete的每次執行,字段的索引都必須重新計算更新。

    那麼在什麼時候適合加上索引呢?我們看一個Mysql手冊中舉的例子,這裏有一條sql語句:

    SELECT c.companyID, c.companyName FROM Companies c, User u WHERE c.companyID = u.fk_companyID AND c.numEmployees >= 0 AND c.companyName LIKE '%i%' AND u.groupID IN (SELECT g.groupID FROM Groups g WHERE g.groupLabel = 'Executive')

    這條語句涉及3個表的聯接,並且包括了許多搜索條件比如大小比較,Like匹配等。在沒有索引的情況下Mysql需要執行的掃描行數是77721876行。而我們通過在companyID和groupLabel兩個字段上加上索引之後,掃描的行數只需要134行。在Mysql中可以通過Explain Select來查看掃描次數。可以看出來在這種聯表和複雜搜索條件的情況下,索引帶來的性能提升遠比它所佔據的磁盤空間要重要得多。

    那麼索引是如何實現的呢?大多數DB廠商實現索引都是基於一種數據結構——B樹。因爲B樹的特點就是適合在磁盤等直接存儲設備上組織動態查找表。B樹的定義是這樣的:一棵m(m>=3)階的B樹是滿足下列條件的m叉樹:

    1、每個結點包括如下作用域(j, p0, k1, p1, k2, p2, ... ki, pi) 其中j是關鍵字個數,p是孩子指針

    2、所有葉子結點在同一層上,層數等於樹高h

    3、每個非根結點包含的關鍵字個數滿足[m/2-1]<=j<=m-1

    4、若樹非空,則根至少有1個關鍵字,若根非葉子,則至少有2棵子樹,至多有m棵子樹

    看一個B樹的例子,針對26個英文字母的B樹可以這樣構造:

    可以看到在這棵B樹搜索英文字母複雜度只爲o(m),在數據量比較大的情況下,這樣的結構可以大大增加查詢速度。然而有另外一種數據結構查詢的虛度比B樹更快——散列表。Hash表的定義是這樣的:設所有可能出現的關鍵字集合爲u,實際發生存儲的關鍵字記爲k,而|k|比|u|小很多。散列方法是通過散列函數h將u映射到表T[0,m-1]的下標上,這樣u中的關鍵字爲變量,以h爲函數運算結果即爲相應結點的存儲地址。從而達到可以在o(1)的時間內完成查找。
    然而散列表有一個缺陷,那就是散列衝突,即兩個關鍵字通過散列函數計算出了相同的結果。設m和n分別表示散列表的長度和填滿的結點數,n/m爲散列表的填裝因子,因子越大,表示散列衝突的機會越大。
    因爲有這樣的缺陷,所以數據庫不會使用散列表來做爲索引的默認實現,Mysql宣稱會根據執行查詢格式嘗試將基於磁盤的B樹索引轉變爲和合適的散列索引以追求進一步提高搜索速度。我想其它數據庫廠商也會有類似的策略,畢竟在數據庫戰場上,搜索速度和管理安全一樣是非常重要的競爭點

 

 

4.數據庫學習-索引設計準則

  設計索引時需要遵循的準則包括:數據庫準則、查詢準則、列準則。以下詳細列出了各個準則詳細說明。其中13屬於數據庫準則;28屬於查詢準則;915屬於列準則。  

 

 1. 一個表如果建有大量索引會影響INSERTUPDATEDELETE語句的性能,因爲在表中的數據更改時,所有索引都須進行適當的調整。 避免對經常更新的表進行過多的索引,並且索引應保持較窄,就是說,列要儘可能少。   


 2. 使用多個索引可以提高更新少而數據量大的查詢的性能。大量索引可以提高不修改數據的查詢(例如SELECT語句)的性能,因爲查詢優化器有更多的索引可供選擇,從而可以確定最快的訪問方法。  


 3. 對小表進行索引可能不會產生優化效果,因爲查詢優化器在遍歷用於搜索數據的索引時,花費的時間可能比執行簡單的表掃描還長。因此,小表的索引可能從來不用,但仍必須在表中的數據更改時進行維護。  


 4. 視圖包含聚合、表聯接或聚合和聯接的組合時,視圖的索引可以顯著地提升性能。若要使查詢優化器使用視圖,並不一定非要在查詢中顯式引用該視圖。


 5. 爲經常用於查詢中的謂詞和聯接條件的所有列創建非聚集索引。避免添加不必要的列。添加太多索引列可能對磁盤空間和索引維護性能產生負面影響。 


 6. 涵蓋索引可以提高查詢性能,因爲符合查詢要求的全部數據都存在於索引本身中。也就是說,只需要索引頁,而不需要表的數據頁或聚集索引來檢索所需數據,因此,減少了總體磁盤I/O。例如,對某一表(其中對列a、列b和列c創建了組合索引)的列a和列b的查詢,僅僅從該索引本身就可以檢索指定數據。 


 7. 將批量insertupdate的操作寫入單個語句內,而不要使用多個SQL語句操作相同的行。僅使用一個語句,就可以利用優化的索引維護。 


 8. 評估查詢類型以及如何在查詢中使用列。例如,在完全匹配查詢類型中使用的列就適合用於非聚集索引或聚集索引。 


 9. 對於聚集索引,請保持較短的索引鍵長度。另外,對唯一列或非空列創建聚集索引可以使聚集索引獲益。 


 10. 不能將ntexttextimagevarchar(max)nvarchar(max) varbinary(max) 數據類型的列指定爲索引鍵列。不過,varchar(max)nvarchar(max)varbinary(max) xml數據類型的列可以作爲非鍵索引列參與非聚集索引。 


 11. xml數據類型的列只能在XML索引中用作鍵列。 


 12. 檢查列的唯一性。在同一個列組合的唯一索引而不是非唯一索引提供了有關使索引更有用的查詢優化器的附加信息。 


 13. 在列中檢查數據分佈。通常情況下,爲包含很少唯一值的列創建索引或在這樣的列上執行聯接將導致長時間運行的查詢。這是數據和查詢的基本問題,通常不識別這種情況就無法解決這類問題。例如,如果物理電話簿按姓的字母順序排序,而城市裏所有人的姓都是SmithJones,則無法快速找到某個人。 


 14. 如果索引包含多個列,則應考慮列的順序。用於等於 (=)、大於 (>)、小於 (<) BETWEEN搜索條件的WHERE子句或者參與聯接的列應該放在最前面。其他列應該基於其非重複級別進行排序,就是說,從最不重複的列到最重複的列。 
例如,如果將索引定義爲LastNameFirstName,則該索引在搜索條件爲WHERE LastName = ‘Smith’ WHERE LastName = Smith AND FirstName LIKE ‘J%’ 時將很有用。不過,查詢優化器不會將此索引用於基於FirstName (WHERE FirstName = ‘Jane’) 而搜索的查詢。  


 15. 考慮對計算列進行索引。



轉載自:索引機制、索引技術、索引設計準則

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章