Microsoft SQL Server 2000 超級管理手冊(十七)

17. 建立與使用索引

什麼是索引?

索引概念

建立索引

重新建置索引

使用索引

設計有效的索引

本章總結

對資料庫設計者而言,索引是最有用的工具之一。 索引 (index)是一個讓您能增進查詢效能的輔助結構,它能減少檢索查詢資料所必須的I/O動作數量。換言之,索引讓Microsoft SQL Server 2000以較少的I/O操作來找出資料,減少搜尋資料的量。當您使用資料庫資料表的索引來檢索資料列時,SQL Server能很快地判斷出資料儲存的位置並且立即擷取該資料。因此,資料庫資料表的索引與書本所用的索引相當類似-兩者均提供快速擷取的功能,特別是我們面對大量資訊的時候。

在本章中,您將學到索引的基本觀念,包括如何建立索引以及SQL Server中有哪幾種不同類型的索引可用。您也會學到何時應使用索引、何時不使用索引-因為索引並非無往不利的工具,在某些情況下,使用索引反而可能有害於系統的效能。

什麼是索引?
 

如前所述,索引是SQL Server用來存取資料的輔助資料結構。依其類型的不同,索引可能是與資料一起儲存,也可能與資料分開儲存。撇開其類型不談,索引的運作方式基本上是相同的,這也是本節中您將學到的部分。

在一個沒有索引的系統中,所有資料檢索的工作都要靠掃描資料表來完成。在掃描資料表的操作中,所有的資料都需要被讀取,並且與查詢的資料相互比對。一般說來,我們會盡量避免資料表掃描-因為這種操作會造成驚人的I/O數量,尤其是掃描一份龐大的資料表時,可能要花掉不少的時間並吃掉可觀的系統資源。如果使用索引的話,您便能具體的降低I/O操作的數量,提昇資料存取的速度並盡快將系統資源釋放給其他的作業來使用。

資料庫索引是以B型樹狀結構來組織。索引中的每一分頁被稱作 索引分頁  索引節點 。索引結構由頂層的根節點開始。 根節點 (root node)標示出索引的起點;當需要尋找資料時,它是最先被存取的資料。根節點也包含了一些索引資料列;這些索引資料列含有一個鍵值及一個稱為中介節點的指標指向另一個索引分頁,如圖17-1所示。這種組態是必須的,因為在一個平均大小的資料表中,索引可能是由成千上萬的索引分頁來構成。藉著由根節點起始並瀏覽中介節點,SQL Server能夠「放大」您要的資料。


 

圖17-1 根節點與中介節點

當我們使用書本中的索引時,使用的方法可能與下面所述極為類似:假設索引是由一頁包含「a」、「b」、「c」等字母項目所在部分之頁碼的目錄頁所開始。接著翻到「a」這一頁,又會發現進入「aa-ab」、「ac-ad」、「ae-af」等範圍所在部分的頁碼。進入「aa」,裡面又列有「aaa-aab」、「aac-aad」、「aad-aaf」等範圍所在部分的頁碼。藉著這種排列,您可以很快的找到您要的資料,而不用翻遍整本書。索引以根節點作為第一頁,與上述方式相當雷同。

一如根節點,每個中介節點包含有索引分頁,分頁中包含著索引資料列。每個索引資料列指向其他的中介節點或分葉節點,如圖17-2。分葉節點由索引的最底層組成。與根節點不同的是,每個中介節點還包含了一份連接到同一層中介節點的連結清單(Linked List)。換句話說,此節點知道相鄰節點以及較低層級的節點。

顧名思義,所謂「B型樹」,意味著從根節點展開中介節點後其型態猶如樹枝般分佈。每一組樹狀結構中同一層的中介節點稱為 索引層級 ,如圖17-3所示。到達分葉節點(樹狀結構中最底層的節點)所需的I/O操作數量要依索引層級的數目而定。如果資料庫資料表含有的資料很少,根節點可以直接指向分葉節點,索引將不需要包含任何中介節點(當然這種情況不太可能發生)。


 

圖17-2 顯示中介節點與分葉節點的樹


 

圖17-3 索引層級

在一個非叢集索引中,分葉節點包含有鍵值,以及一個指向資料表中所需資料列的資料列識別碼(ROW ID),或者會包含一個叢集索引鍵值-如果資料表中還有一個叢集索引的話。而在叢集索引中,資料本身即位在分葉節點中(叢集與非叢集索引將在本章稍後 〈索引類型〉 一節中有所說明)。分葉節點中資料列的數量要看索引建立時引用的項目大小。而在叢集索引中,則要視資料的大小而定。


說明

資料列識別碼(ROW ID)是SQL Server由檔案編號、分頁碼及資料列號碼自動建立的指標。藉著資料列識別碼,您只需一個額外的I/O操作便可擷取資料。因為您知道要擷取的是哪個分頁,而且SQL Server知道分頁所在的位置,因此只要單一的I/O操作即可將該分頁讀入記憶體之中。這種檢索過程的簡化也是為何索引能更有效率並增進效能的主要原因。


要特別留心的是,由於索引是以排序方式建立的,任何資料的變更都可能造成額外的負擔。舉例來說,如果插入動作造成一個新的資料列必須被插入到已經滿的分葉節點,SQL Server必須挪出空間給新的資料列。此舉必須將近乎半數的資料列移至分葉節點中的另一個分頁中。此種資料搬移稱為 分頁分隔 (Page Split)。分頁分隔會造成索引樹一連串的分隔動作。透過謹慎的設定 填滿因數 (fill factor)可以避免分頁分隔,我們會在本章稍後 〈使用填滿因數避免分頁分隔〉 一節中介紹填滿因數。

索引概念
 

現在您已經對索引結構有了基本的瞭解,接著讓我們看一些與索引有關的概念。在本節中,您將學到索引鍵、索引唯一性以及索引的類型。

索引鍵
 

 索引鍵 (index key)指出用於產生索引的一個資料行或數個資料行。索引鍵是一個讓您可以快速找到資料列的值,此資料列包含有您需要的資料。索引鍵就像是書本中的索引項目,可指向文中特定的主題。要使用索引取得資料列,您必須在SQL陳述式的WHERE子句中包含索引鍵值,還得要看看索引是一個簡單索引還是複合索引。

簡單索引
 

 簡單索引 (simple index)即為使用單一資料行的索引,如圖17-4。如果您要取得索引的效率,則該資料行必須在SQL陳述式的WHERE子句中引用。


 

圖17-4 簡單索引

根據資料儲存的資料型別、以及資料行中唯一性項目的數量,還有使用何種類型SQL陳述式等等因素,有時使用簡單索引便可以很有效率,但有些情況則可能使用複合索引會比較合適。舉例來說,如果您索引的是一個由上千個名字與地址構成的通訊錄, state資料行就不應該是一個簡單索引的候選鍵,因為同一州裡可能有很多相同的項目。然而,若在索引中增加street與city資料行,使其成為複合索引,您可以讓每個項目近乎唯一。這種方法會很有用-若您的查詢是依地址來找資料列的話。

複合索引
 

 複合索引 (composite index)是定義超過一個資料行的索引,如圖17-5。複合索引可以利用一個多或個索引鍵來存取。在SQL Server 2000中,索引最多可包含16個資料行,並且鍵值總資料長度不可超過900個位元組。


 

圖17-5 複合索引

當您使用複合索引進行查詢時,並不需要在SQL陳述式的WHERE子句中放入所有的索引鍵,不過使用一個以上的索引鍵會是比較聰明的做法。舉例來說,假設索引是由資料表中a、b、c三個資料行建立的,使用包含有(a AND b AND c)或(a AND b)或a的SQL陳述式均可存取該索引。當然,使用最嚴格的WHERE子句,例如包含a AND b AND c,效率會比較高些。它能從資料庫中檢索出較少的資料列,因為它檢驗資料列時更為明確。如果您使用a AND b或只有a,會開始進行索引掃描的操作。

當超過一個索引項目可以滿足搜尋條件時,就會發生索引掃描。在索引掃描中,索引的節點會被掃描以取得多個資料集。此外,索引只部分涵蓋了選取的值。舉例來說,如果索引是由a、b、c三個資料行建立而查詢僅指定了a,所有滿足a的值的資料列都會被傳回,包括所有b和c的值。

由於使用在索引中的基礎資料行是按數字排列,SQL Server查詢最佳化器可以判斷出大略包含您所需資料的索引分頁範圍。一旦知道了開始頁和結束頁,含有資料值的所有分頁都將被檢索,而且資料將被掃描以選擇您所需的資料。


 真實世界 CustomerLocation資料表 

假設我們現有一份資料表,其中包含了我們公司顧客地址的相關資訊。索引是由state、country以及city資料行所建立,並以 state  country  city 的順序儲存在B型樹狀結構中。如果一個查詢在WHERE子句中指定 state 的值為 Texas ,將會使用索引的功能。由於查詢中 country  city 的值並未指定,索引將會傳回索引資料集中所有state資料行值為 Texas 的資料列。索引掃描會先用來檢索出索引分頁的範圍,隨後依state資料行的值擷取資料分頁。索引分頁將被循序的讀取,方式與資料表掃描存取資料分頁一樣。



說明

如果您要使用索引的特色,只有在SQL查詢的WHERE子句中至少用到一個索引鍵時,索引才會起作用。以剛剛的例子來說,如果查詢的WHERE子句裡只有名字或電話這類資料行的話,就不會用到索引的功能。


在大部分的情況下,索引掃描十分有效率。不過,若資料表中將有20% 以上的資料列會被存取,使用讀取資料表中所有資料列的資料表掃描會更有效率。索引利用的查詢效率,要視您如何使用索引(本章稍後 〈使用索引〉 一節會介紹)以及我們接著要討論的問題:索引的唯一性。

索引的唯一性
 

您可以將SQL Server的索引定義為唯一索引或非唯一索引。在 唯一性索引 (unique index)中,每個索引鍵的值必須是唯一的。 非唯一性索引 (nonunique index)則允許索引鍵的值可以重複。非唯一索引的效力或效率要看索引的選擇性而定。

唯一索引
 

唯一索引的每個索引鍵只包含一列資料-換句話說,索引鍵值在資料表中不會出兩次。唯一索引非常有效率,因為它們保證要擷取查詢所需的資料只需一個額外的I/O操作。SQL Server會強制一個或數個資料行的唯一性以建立索引鍵。SQL Server將不會允許在資料庫中插入重複的鍵值,如果您試圖這麼做,則會傳回錯誤訊息。當您在資料表中建立一個PRIMARY KEY條件約束或一個UNIQUE條件約束時,SQL Server便會建立唯一性索引。PRIMARY KEY條件約束與UNIQUE條件約束已經在 第16章 中討論過。

當資料本身即是唯一的,索引自然可以建立其唯一性。但若資料行中所包含的資料並不是唯一的,您仍然可以利用複合索引來建立唯一索引。舉例來說,last name資料行可能並不是唯一的,但是若與first name和middle name資料行組合起來,您便能在資料表上建立唯一索引。


說明

如果您在資料表中插入一資料列的結果可能會使唯一索引出現重複的索引鍵值,這個插入動作將會失敗。


非唯一索引
 

非唯一性索引的運作方式與唯一性索引並沒有什麼不一樣(除了可以在分葉節點中包含重複的值以外)。只要符合SELECT陳述式中指定的基準,所有重複的值都會被擷取。

非唯一性索引並不如唯一性索引般那麼有效率,因為它需要額外的程序(額外的I/O操作)來檢索出查詢所需的資料。不過有些應用程式需要用到重複的鍵值,它有可能無法建立唯一索引。在這類情況下,非唯一索引至少比沒有索引要來得好些。

索引類型
 

B型樹狀結構索引有兩種類型: 叢集索引 (clustered indexes)與 非叢集索引 (nonclustered indexes)。叢集索引在其分葉節點中儲存實際資料的資料列。非叢集索引則是一個指出資料表中資料位置的輔助結構。在本節中,我們將看一下兩種索引類型之間不同的地方。我們也會在本節中介紹 全文檢索索引 (full-text index),它實際上更像是一個目錄而非索引。

叢集索引
 

一如前述,叢集索引是一種將資料表的實際資料列資料按順序儲存在其分葉節點的B型樹狀結構索引,如圖17-6。這種系統提供了一些優點與缺點。


 

圖17-6 叢集索引

由於叢集索引的資料是儲存在分葉節點上,亦即一旦到達分葉節點便可取用資料,這種方式意味著只要少數I/O操作便可得出結果。任何操作數量的減少都可使單一操作產生較高的效能,並對系統整體的效能有所提昇。

叢集索引的另一個優點是,資料將會按索引排序時的順序來擷取。舉例來說,如果現在有一個叢集索引是由state、country、city資料行來建立,而查詢選擇所有的state ? Texas的值,輸出的結果將會以country和city資料行在索引定義時的排序方式來排序。如果應用程式與資料庫在設計時考量過這類問題,這種功能就可以讓您避免不必要的排序操作。例如,若您已經確定資料需要的排序方式並用於索引之中,使用叢集索引便可讓您在擷取資料之後不需再執行排序的工作。

使用叢集索引的一個缺點是,存取資料表時常需穿梭整個索引,如此將會造成系統額外的負擔。SQL Server存取資料時會從根節點開始搜尋索引直到它到達包含資料的分葉節點。如果由於資料數量的緣故建立了許多分葉節點,支援這些分葉節點所需的索引層級數量也相當多,SQL Server從根節點到分葉節點的搜尋過程就會需要更多的I/O操作。

因為實際資料是儲存在叢集索引中,在一個資料表上您只能建立一個叢集索引。另一方面,您可以在叢集資料表的頂層建立不只一個非叢集索引。(叢集資料表僅僅是擁有一個叢集索引的資料表。)您應該使用最常用以存取的索引鍵來建立叢集索引,如此可讓您在最佳時機透過叢集索引存取資料,並提供最好的效能。

非叢集索引
 

不同於叢集索引,非叢集索引並不會把實際資料包含在其分葉節點之中。分葉節點包含著兩種資料列的位置資訊其中的一種。第一,如果資料表上沒有叢集索引,此資料表的非叢集索引的分葉節點儲存的是資料列識別碼,如圖17-7。每個資料列識別碼指向資料表中實際資料存在的資料列。構成資料列識別碼的值包括資料檔案識別碼、分頁碼,以及分頁中的資料列編號。這個值精確的指出資料儲存的位置以便快速的存取實際資料。


 

圖17-7 在沒有叢集索引的資料表上的非叢集索引

如果資料表上有一個叢集索引,非叢集索引的分葉節點將會包含此資料的叢集索引鍵值,如圖17-8。當到達非叢集索引的分葉節點時,可找到叢集索引鍵值,並且接著被用在叢集索引中繼續搜尋,直到在叢集索引的分葉節點中找到資料為止。


 

圖17-8 一個擁有叢集索引的資料表上的非叢集索引

之前已經說過,每個資料表只能擁有一個叢集索引。您可以在每個資料表上建立249個非叢集索引,但那絕不是聰明的做法(本章稍後 〈索引指導原則〉 一節中會解釋這一點)。在資料表不同的資料行上擁有幾個非叢集索引是很常見的,WHERE子句要用到哪個索引則由查詢最佳器來決定。

全文檢索索引
 

如前所述,SQL Server全文檢索索引事實上比較像是一個目錄而不是索引,並且也不是B型樹狀結構。全文檢索索引允許您以關鍵字的群組來搜尋資料。全文檢索索引是Microsoft Search Services的一部分,並廣泛地應用在Web網站搜尋引擎以及其他以文字為基礎的操作中。

不同於B型樹狀結構索引,全文檢索索引儲存在資料庫的外部,但是由資料庫來維護。由於它是儲存在外部,索引可以自行維護其結構。執行全文檢索索引有下列限制:

  • 全文檢索索引中必須包含一個資料行,並且該資料行在資料表中的每一列都要是唯一的。
     
  • 全文檢索索引也必須包含資料表中一個或多個字元資料型別的資料行。
     
  • 每一個資料表只可以允許有一個全文檢索索引。
     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值