轉自http://blog.csdn.net/single_wolf_wolf/article/details/52915862數據庫
1、理解索引的結構ide
索引在數據庫中的做用相似於目錄在書籍中的做用,用來提升查找信息的速度。使用索引查找數據,無需對整表進行掃描,能夠快速找到所需數據。微軟的SQL SERVER提供了兩種索引:彙集索引(clustered index,也稱聚類索引、簇集索引)和非彙集索引(nonclustered index,也稱非聚類索引、非簇集索引)。性能
SQL Server 中數據存儲的基本單位是頁(Page)。數據庫中的數據文件(.mdf 或 .ndf)分配的磁盤空間能夠從邏輯上劃分紅頁(從 0 到 n 連續編號)。磁盤 I/O 操做在頁級執行。也就是說,SQL Server 每次讀取或寫入數據的最少數據單位是數據頁。測試
下面咱們先簡單的瞭解一下索引的體系結構:.net
1. 彙集索引結構code
在 SQL Server 中,索引是按 B 樹結構進行組織的。blog
彙集索引單個分區中的結構:排序
--創建UserAddDate彙集索引 CREATE CLUSTERED INDEX [IX_AddDate] ON [User] ( [AddDate] ASC )
彙集索引(Clustered Index)特色索引
2. 非彙集索引結構get
非彙集索引與彙集索引具備相同的 B 樹結構,它們之間的顯著差異在於如下兩點:
1. 基礎表的數據行不按非彙集鍵的順序排序和存儲。
2. 非彙集索引的葉層是由索引頁而不是由數據頁組成。
下圖示意了單個分區中的非彙集索引結構:
包含列的索引
經過將包含列(稱爲非鍵列)添加到索引的葉級,能夠擴展非彙集索引的功能。鍵列存儲在非彙集索引的全部級別,而非鍵列僅存儲在葉級別。
下面舉個簡單的例子來講明一下彙集索引和非彙集索引的區別:
咱們有一本漢語字典,能夠把它的正文自己看作是一個彙集索引,它是按照漢字拼音的開頭字母排序的,再也不須要查找其餘目錄。當遇到不認識的字時,須要結合「部首目錄」和「檢字表」, 先找到目錄中的結果,而後再翻到您所須要的頁碼。經過這種方法查到的目錄中字的排序並非真正的正文的排序方法。把這種看作是一個非彙集索引。
另外,請注意每一個表只能有一個彙集索引。
--創建UserAddDate非彙集索引 CREATE NONCLUSTERED INDEX [IX_AddDate] ON [User] ( [AddDate] ASC )
非彙集索引 (Unclustered Index) 特色
2、選擇創建哪一種索引
1. 什麼時候建立彙集索引更能提升性能
Clustered Index會提升大多數table的性能,尤爲是當它知足如下條件時:
獨特, 狹窄, 持續增加的,最好是隻向上增長。例如:
2. 非彙集索引提升性能的方法
非彙集索引因爲B樹的節點不是具體數據頁,有時候因爲這個緣由,會致使非彙集索引甚至不如表遍從來的快。可是,非彙集索引有個特性,若是你要查詢的內容,在非彙集索引中以及被覆蓋到了,則不須要繼續到彙集索引,或者RID(heap結構中的行標識符)中去尋找數據了,這時候就能夠很大的提升性能,這就是覆蓋面(Covering) 的問題。
因爲彙集索引葉子節點就是具體數據,因此彙集索引的覆蓋率是100%, 經過提升覆蓋面來提升性能的問題也就只有非彙集索引(Nonclustered Indexes)才存在。
當查詢中全部的columns都包括在index上時,咱們說這 index covers the query. Columns的順序在此不重要(Select 時候的順序不重要,可是Index 創建的順序可得當心了)。
在 SQL Server 2005 中,爲了提升這種 Covering 帶來的好處,甚至能夠經過將非鍵列添加到非彙集索引的葉級別來擴展非彙集索引的功能。
補充:只有查詢在具備高度選擇性的狀況下,非彙集索引纔有優點。
3、使用匯集索引或非彙集索引的場景 (注:優先級依次爲推薦,應,不該)
4、主鍵和彙集索引的比較
如下是一些大衆點評網中測試使用的示例:
CHECKPOINT DBCC DROPCLEANBUFFERS SET STATISTICS IO ON declare @d datetime set @d=getdate() SELECT * FROM User WHERE AddDate>'2008-06-01' AND AddDate<'2008-06-10' select [語句執行花費時間(毫秒)]=datediff(ms,@d,getdate()) --(45077 行受影響) --表'User'。掃描計數1,邏輯讀取1103 次,物理讀取2 次,預讀1090 次,lob 邏輯讀取0 次,lob 物理讀取0 次,lob 預讀0 次。 --2543 CHECKPOINT DBCC DROPCLEANBUFFERS SET STATISTICS IO ON declare @d datetime set @d=getdate() SELECT * FROM User WITH (INDEX=IX_AddDate) WHERE AddDate>'2008-06-01' AND AddDate<'2008-06-10' select [語句執行花費時間(毫秒)]=datediff(ms,@d,getdate()) --(45077 行受影響) --表'User'。掃描計數1,邏輯讀取45165 次,物理讀取133 次,預讀141 次,lob 邏輯讀取0 次,lob 物理讀取0 次,lob 預讀0 次。 --3860
5、使用索引的代價
引用: http://kb.cnblogs.com/page/144409/