索引全攻略

一 概述    能夠利用索引快速訪問數據庫表中的特定信息。索引是對數據庫表中一個或多個列的值進行排序的結構。    索引提供指針以指向存儲在表中指定列的數據值,而後根據指定的排序次序排列這些指針。    數據庫使用索引的方式與使用書的目錄很類似:經過搜索索引找到特定的值,    而後跟隨指針到達包含該值的行 二 索引的兩種類型: 彙集索引=簇集索引 彙集索引基於數據行的鍵值在表內排序和存儲這些數據行。因爲數據行按基於彙集索引鍵的排序次序存儲, 所以彙集索引對查找行頗有效。每一個表只能有一個彙集索引,由於數據行自己只能按一個順序存儲。 數據行自己構成彙集索引的最低級別。 只有當表包含彙集索引時,表內的數據行才按排序次序存儲。若是表沒有彙集索引, 則其數據行按堆集方式存儲。 彙集索引對於那些常常要搜索範圍值的列特別有效。使用匯集索引找到包含第一個值的行後, 即可以確保包含後續索引值的行在物理相鄰。例如,若是應用程序執行的一個查詢常常檢索某一日期範圍 內的記錄,則使用匯集索引能夠迅速找到包含開始日期的行,而後檢索表中全部相鄰的行, 直到到達結束日期。這樣有助於提升此類查詢的性能。一樣,若是對從表中檢索的數據進行排序時 常常要用到某一列,則能夠將該表在該列上彙集(物理排序),避免每次查詢該列時都進行排序, 從而節省成本 非彙集索引 非彙集索引具備徹底獨立於數據行的結構。非彙集索引的最低行包含非彙集索引的鍵值, 而且每一個鍵值項都有指針指向包含該鍵值的數據行。數據行不按基於非彙集鍵的次序存儲。 在非彙集索引內,從索引行指向數據行的指針稱爲行定位器。 行定位器的結構取決於數據頁的存儲方式是堆集仍是彙集。對於堆集,行定位器是指向行的指針。 對於有彙集索引的表,行定位器是彙集索引鍵。 只有在表上建立了彙集索引時,表內的行才按特定的順序存儲。這些行就基於彙集索引鍵按順序存儲。 若是一個表只有非彙集索引,它的數據行將按無序的堆集方式存儲 非彙集索引能夠建多個,二者都能改善查詢性能 非彙集索引與彙集索引同樣有 B 樹結構,可是有兩個重大差異: 數據行不按非彙集索引鍵的順序排序和存儲。 非彙集索引的葉層不包含數據頁。 相反,葉節點包含索引行。每一個索引行包含非彙集鍵值以及一個或多個行定位器, 這些行定位器指向有該鍵值的數據行(若是索引不惟一,則多是多行)。 非彙集索引能夠在有彙集索引的表、堆集或索引視圖上定義 另外 惟一索引 惟一索引能夠確保索引列不包含重複的值。在多列惟一索引的狀況下,該索引能夠確保索引列中每一個值組 合都是惟一的。惟一索引既是索引也是約束。 複合索引 索引項是多個的就叫組合索引,也叫複合索引。複合索引使用時須要注意索引項的次序。 二 索引的建立 有兩種方法能夠在 SQL Server 內定義索引: CREATE INDEX 語句和CREATE TABLE 語句 CREATE TABLE支持在建立索引時使用下列約束: PRIMARY KEY 建立惟一索引來強制執行主鍵 UNIQUE 建立惟一索引 CLUSTERED 建立彙集索引 NONCLUSTERED 建立非彙集索引 注: 1 定義索引時,能夠指定每列的數據是按升序仍是降序存儲。若是不指定,則默認爲升序     2 支持在計算列上建立索引     3 爲索引指定填充因子       可標識填充因子來指定每一個索引頁的填滿程度。索引頁上的空餘空間量很重要,       由於當索引頁填滿時,系統必須花時間拆分它以便爲新行騰出空間。 三 索引的維護語句 DBCC DBREINDEX    重建指定數據庫中表的一個或多個索引 DBCC INDEXFRAG  整理指定的表或視圖的彙集索引和輔助索引碎片 比較              速度    兼容性     日誌影響      數據訪問影響       額外磁盤空間 DBCC        最快      最好     大,但能經過把   操做過程當中數據不   須要大 DBREINDEX             能夠重   故障還原模型設  能訪問,影響大                       建全部   爲簡單減小日誌                          有索引 DBCC        慢       但可   必須分   小              數據未被鎖定        須要小 INDEXDEFRAG          隨時終 別指定                      止執行                                   drop index    中等  必須分   大,但能經過把    僅在操做執行時    中等,操做在    create index        別指定   故障還原模型設   鎖定數據          tempdb中進行                              爲簡單減小日誌 四 查看索引的方法 sp_indexes        返回指定遠程表的索引信息 INDEXKEY_PROPERTY 返回有關索引鍵的信息 sysindexes系統表  數據庫中的每一個索引和表在表中各佔一行,該表存儲在每一個數據庫中 五 能夠經過執行計劃    查看sql語句執行時是否創建在索引之上 好比 CREATE TABLE Test (Field_1 int NOT NULL,  Field_2 int CONSTRAINT PK_Test  PRIMARY KEY CLUSTERED (Field_1)) CREATE index IX_Test ON Test (Field_2) 1 SELECT * FROM Test WHERE Field_2 =408   執行計劃能夠看出使用了IX_Test索引 2 SELECT * FROM Test WHERE Field_1 =1   執行計劃能夠看出使用了PK_Test 3 但若是是SELECT * FROM Test with (index(IX_Test)) WHERE Field_1 =1   則指定使用索引 六 索引的具體使用 (轉貼) 1) 索引的設計 A:儘可能避免表掃描 檢查你的查詢語句的where子句,由於這是優化器重要關注的地方。包含在where裏面的每一列(column)都是可能的侯選索引,爲能達到最優的性能,考慮在下面給出的例子:對於在where子句中給出了column1這個列。 下面的兩個條件能夠提升索引的優化查詢性能! 第一:在表中的column1列上有一個單索引 第二:在表中有多索引,可是column1是第一個索引的列 避免定義多索引而column1是第二個或後面的索引,這樣的索引不能優化服務器性能 例如:下面的例子用了pubs數據庫。 SELECT au_id, au_lname, au_fname FROM authors WHERE au_lname = ’White’ 按下面幾個列上創建的索引將會是對優化器有用的索引 ?au_lname ?au_lname, au_fname 而在下面幾個列上創建的索引將不會對優化器起到好的做用 ?au_address ?au_fname, au_lname 考慮使用窄的索引在一個或兩個列上,窄索引比多索引和複合索引更能有效。用窄的索引,在每一頁上 將會有更多的行和更少的索引級別(相對與多索引和複合索引而言),這將推動系統性能。 對於多列索引,SQL Server維持一個在全部列的索引上的密度統計(用於聯合)和在第一個索引上的 histogram(柱狀圖)統計。根據統計結果,若是在複合索引上的第一個索引不多被選擇使用,那麼優化器對不少查詢請求將不會使用索引。 有用的索引會提升select語句的性能,包括insert,uodate,delete。 可是,因爲改變一個表的內容,將會影響索引。每個insert,update,delete語句將會使性能降低一些。實驗代表,不要在一個單表上用大量的索引,不要在共享的列上(指在多表中用了參考約束)使用重疊的索引。 在某一列上檢查惟一的數據的個數,比較它與表中數據的行數作一個比較。這就是數據的選擇性,這比較結果將會幫助你決定是否將某一列做爲侯選的索引列,若是須要,建哪種索引。你能夠用下面的查詢語句返回某一列的不一樣值的數目。 select count(distinct cloumn_name) from table_name 假設column_name是一個10000行的表,則看column_name返回值來決定是否應該使用,及應該使用什麼索引。 Unique values Index 5000 Nonclustered index 20 Clustered index 3 No index 2) 鏃索引和非鏃索引的選擇 <1:>鏃索引是行的物理順序和索引的順序是一致的。頁級,低層等索引的各個級別上都包含實際的數據頁。一個表只能是有一個鏃索引。因爲update,delete語句要求相對多一些的讀操做,所以鏃索引經常能加速這樣的操做。在至少有一個索引的表中,你應該有一個鏃索引。 在下面的幾個狀況下,你能夠考慮用鏃索引: 例如: 某列包括的不一樣值的個數是有限的(可是不是極少的) 顧客表的州名列有50個左右的不一樣州名的縮寫值,可使用鏃索引。 例如: 對返回必定範圍內值的列可使用鏃索引,好比用between,>,>=,<,<=等等來對列進行操做的列上。 select * from sales where ord_date between ’5/1/93’ and ’6/1/93’ 例如: 對查詢時返回大量結果的列可使用鏃索引。 SELECT * FROM phonebook WHERE last_name = ’Smith’ 當有大量的行正在被插入表中時,要避免在本表一個天然增加(例如,identity列)的列上創建鏃索引。若是你創建了鏃的索引,那麼insert的性能就會大大下降。由於每個插入的行必須到表的最後,表的最後一個數據頁。 當一個數據正在被插入(這時這個數據頁是被鎖定的),全部的其餘插入行必須等待直到當前的插入已經結束。 一個索引的葉級頁中包括實際的數據頁,而且在硬盤上的數據頁的次序是跟鏃索引的邏輯次序同樣的。 <2:>一個非鏃的索引就是行的物理次序與索引的次序是不一樣的。一個非鏃索引的葉級包含了指向行數據頁的指針。 在一個表中能夠有多個非鏃索引,你能夠在如下幾個狀況下考慮使用非鏃索引。 在有不少不一樣值的列上能夠考慮使用非鏃索引 例如:一個part_id列在一個part表中 select * from employee where emp_id = ’pcm9809f’ 查詢語句中用order by 子句的列上能夠考慮使用鏃索引   3) 一個表列若是設爲主鍵(primary key),它會自動生成一個聚簇索引 這時不能直接使用Drop index Table1.Tableindex1語句 必須刪除主鍵約束,用語句:alter table table1 drop constraint 約束名(如pk_xxx) 最後補充 全文索引請參考 [url]http://expert.csdn.net/Expert/topic/1594/1594455.xml?temp=.1432154[/url]
相關文章
相關標籤/搜索