咱們都知道創建適當的索引可以提升查詢速度,優化查詢。先說明一下,不管是彙集索引仍是非彙集索引都是B樹結構。數據庫
CREATE TABLE MyTableKeyExample { Column1 int IDENTITY KEY NONCLUSTERED, Column2 int }
索引(index)是除了表以外的另外一個重要的、用戶定義的存儲在數據庫裏的數據結構。當根據索引碼的值搜索數據時,索引提供了對數據的快速訪問。事實上,沒有索引數據庫也可以根據SELECT語句經過表掃描成功地檢索到結果,可是隨着表變得愈來愈大,使用「適當」的索引的效果就愈來愈明顯。但若是使用索引時不認真考慮其實現過程,索引反而有可能會下降數據庫的工做性能。建立主鍵時會自動建立彙集索引,除非當前表中已經含有了彙集索引或是建立主鍵時指定了NONCLUSTERED關鍵字。數據結構
彙集索引、非彙集索引、非彙集惟一索引:post
SqlServer提供了兩種索引:彙集索引和非彙集索引。彙集的做用就是將某一列(或是多列)的物理順序改變爲和邏輯順序相一致。性能
彙集索引(CLUSTERED)與非彙集索引(NONCLUSTERED)的區別:學習
其實,咱們的漢語字典的正文自己就是一個彙集索引(按照拼音的英文字母排序) 好比,咱們要查「安」字 ,就會很天然地翻開字典的前幾頁,由於「安」的拼音是「an」,而按照拼音排序漢字的字典是以英文字 母「a」開頭並以「z」結尾的,那麼「安」字就天然地排在字典的前部。若是您翻完了全部以「a」開頭的部分仍然找不到這個字,那麼就說明您的字典中沒有這個字;一樣的,若是查「張」字,那您也會將您的 字典翻到最後部分,由於「張」的拼音是「zhang」。也就是說,字典的正文部分自己就是一個目錄,您不須要再去查其餘目錄來找到您須要找的內容。咱們把這種正文內容自己就是一種按照必定規則排列的目錄稱爲「彙集索引」。 這也是爲何一張表只能 夠有一個彙集索引的緣由。由於一張表只可以按一種方式排序。 其中彙集索引的葉級節點就是數據。你能夠理解爲有不少列火車,按照火車頭索引(排序),火車頭後面跟着的就是數據。
若是您認識某個字,您能夠快速地從自動中查到這個字。但您也可能會遇到您不認識的字,不知道它的發音,這時候,您就不能按照剛纔的方法找到您要查的字,而須要去根據「偏旁部首」查到您要找的字,而後根據這個字後的頁碼直接翻到某頁來找到您要找的字。但您結合「部首目錄」和「檢字表」而查到的字的排序並非真正的正文的排序方法,好比您查「張」字,咱們能夠看到在查部首以後的檢字表中「張」 的頁碼是672頁,檢字表中「張」的上面是「馳」字,但頁碼倒是63頁,「張」的下面是 「弩」字,頁面390頁。很顯然,這些字並非真正的分別位於「張」字的上下方,如今您看到的連續的「馳、張、弩」 三字實際上就是他們在非彙集索引中的排序,是字典正文中的字在非彙集索引中的映射。咱們能夠經過這種方式來找到您所須要的字,但它須要兩個過程,先找到目錄中的結果,而後再翻到您所須要的頁碼。咱們把這種目錄純粹是目錄,正文純粹是正文的排序方式稱爲「非彙集索引」。優化
實際上若是表上有彙集索引,則非彙集索引中存儲着彙集索引的引用,而後經過利用匯集索引來獲取數據。所以這就是爲何返回少許數據的時候使用非彙集索引的性能較好,而返回大量的數據的時候使用非彙集索引還不如直接全表掃描來得快。而若是表上沒有彙集索引的時候,則引用行號。spa
非彙集索引須要額外的空間進行存儲,按照被索引列進行彙集索引,並在B樹的葉子節點包含指向非彙集索引所在表的指針。非彙集索引也是B樹結構,另一個單獨的B樹。指針
惟一索引:code
當主鍵建立時若是不設置爲彙集索引,那麼就必定是惟一的非彙集索引。實際上,惟一索引,故名思議就是它要求該列上的值是惟一的。對象
彙集索引列能夠重複,非彙集索引列也能夠重複。這就是爲何要有惟一這個東東了。聲明惟一索引的語法很簡單,只是多了個UNIQUE關鍵字。
CREATE UNIQUE NONCLUSTERED INDEX [AK_Product_Name] ON Production.Product ( [Name] );
惟一索引有不少限制和特性。下面詳細學習下惟一索引。
爲表聲明主鍵或惟一約束時,SQL Server會自動建立與之對應的惟一索引。定義一個惟一約束時,SQL Server會自動建立一個與之同名的惟一索引,要刪除索引必須先刪除約束。但刪除約束,刪除約束也會致使與之關聯的索引被刪除,也就是說,不能刪除惟一索引,要刪除索引只有刪除惟一約束這個辦法。
惟一索引依賴於惟一約束,刪除惟一索引必須刪除惟一約束。另外SQL Server又在創建惟一約束時又默認創建惟一索引。
總結起來就是:惟一索引與惟一約束始終一同存在。
由於定義一個主鍵或是定義約束會致使索引被建立,因此你必須在約束定義時就給出必要的索引信息,所以上面ALTER TABLE語句中包含了」CLUSTERED」關鍵字。
ALTER TABLE Production.Product ADD CONSTRAINT PK_Product_ProductID PRIMARY KEY CLUSTERED ( ProductID );
若是惟一索引或約束所約束的列在當前的表中已經含有了重複值,那麼建立索引會失敗。而當惟一索引建立成功後,全部違反這個約束的INSERT、UPDATE語句都會失敗。
消息 2601,級別 14,狀態 1,第 1 行
不能在具備惟一索引 'AK_Product_Name' 的對象
'Production.Product' 中插入重複鍵的行。
語句已終止。
惟一約束和惟一索引並無顯著的區別。建立獨立的惟一索引和使用惟一約束對於數據的驗證方式並沒有區別。查詢優化器也不會區分惟一索引是由約束建立仍是手工建立。然而以數據完整性爲目標的話,最好建立約束,這使得對應的索引的目標一目瞭然。
過濾惟一索引,當咱們須要既容許多個NULL值,又不容許重複的時候,可使用這個:
CREATE UNIQUE NONCLUSTERED INDEX xx on ProductDemo(<索引列>) --指定索引列 where <索引列>!=null) --過濾條件
對於用以上語法建立的惟一索引,插入時,只有當惟一索引列不爲NULL的時候才檢測重複。換句話說,以上表的索引列容許多個NULL值。