程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> SQL索引全攻略

SQL索引全攻略

編輯:關於SqlServer

一 概述

 

可以利用索引快速訪問數據庫表中的特定信息。索引是對數據庫表中一個或多個列的值進行排序的結構。
索引提供指針以指向存儲在表中指定列的數據值,然後根據指定的排序次序排列這些指針。
數據庫使用索引的方式與使用書的目錄很相似:通過搜索索引找到特定的值,
然後跟隨指針到達包含該值的行


二 索引的兩種類型:

聚集索引=簇集索引

聚集索引基於數據行的鍵值在表內排序和存儲這些數據行。由於數據行按基於聚集索引鍵的排序次序存儲,
因此聚集索引對查找行很有效。每個表只能有一個聚集索引,因為數據行本身只能按一個順序存儲。
數據行本身構成聚集索引的最低級別。

只有當表包含聚集索引時,表內的數據行才按排序次序存儲。如果表沒有聚集索引,
則其數據行按堆集方式存儲。

聚集索引對於那些經常要搜索范圍值的列特別有效。使用聚集索引找到包含第一個值的行後,
便可以確保包含後續索引值的行在物理相鄰。例如,如果應用程序執行的一個查詢經常檢索某一日期范圍
內的記錄,則使用聚集索引可以迅速找到包含開始日期的行,然後檢索表中所有相鄰的行,
直到到達結束日期。這樣有助於提高此類查詢的性能。同樣,如果對從表中檢索的數據進行排序時
經常要用到某一列,則可以將該表在該列上聚集(物理排序),避免每次查詢該列時都進行排序,
從而節省成本

非聚集索引

非聚集索引具有完全獨立於數據行的結構。非聚集索引的最低行包含非聚集索引的鍵值,
並且每個鍵值項都有指針指向包含該鍵值的數據行。數據行不按基於非聚集鍵的次序存儲。

在非聚集索引內,從索引行指向數據行的指針稱為行定位器。
行定位器的結構取決於數據頁的存儲方式是堆集還是聚集。對於堆集,行定位器是指向行的指針。
對於有聚集索引的表,行定位器是聚集索引鍵。
只有在表上創建了聚集索引時,表內的行才按特定的順序存儲。這些行就基於聚集索引鍵按順序存儲。
如果一個表只有非聚集索引,它的數據行將按無序的堆集方式存儲
非聚集索引可以建多個,兩者都能改善查詢性能

非聚集索引與聚集索引一樣有 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)

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved