索引全攻略
2024-07-21 02:08:49
供稿:網(wǎng)友
索引問題
一 概述
可以利用索引快速訪問數(shù)據(jù)庫表中的特定信息。索引是對數(shù)據(jù)庫表中一個或多個列的值進(jìn)行排序的結(jié)構(gòu)。
索引提供指針以指向存儲在表中指定列的數(shù)據(jù)值,然后根據(jù)指定的排序次序排列這些指針。
數(shù)據(jù)庫使用索引的方式與使用書的目錄很相似:通過搜索索引找到特定的值,
然后跟隨指針到達(dá)包含該值的行
二 索引的兩種類型:
聚集索引=簇集索引
聚集索引基于數(shù)據(jù)行的鍵值在表內(nèi)排序和存儲這些數(shù)據(jù)行。由于數(shù)據(jù)行按基于聚集索引鍵的排序次序存儲,
因此聚集索引對查找行很有效。每個表只能有一個聚集索引,因為數(shù)據(jù)行本身只能按一個順序存儲。
數(shù)據(jù)行本身構(gòu)成聚集索引的最低級別。
只有當(dāng)表包含聚集索引時,表內(nèi)的數(shù)據(jù)行才按排序次序存儲。如果表沒有聚集索引,
則其數(shù)據(jù)行按堆集方式存儲。
聚集索引對于那些經(jīng)常要搜索范圍值的列特別有效。使用聚集索引找到包含第一個值的行后,
便可以確保包含后續(xù)索引值的行在物理相鄰。例如,如果應(yīng)用程序執(zhí)行的一個查詢經(jīng)常檢索某一日期范圍
內(nèi)的記錄,則使用聚集索引可以迅速找到包含開始日期的行,然后檢索表中所有相鄰的行,
直到到達(dá)結(jié)束日期。這樣有助于提高此類查詢的性能。同樣,如果對從表中檢索的數(shù)據(jù)進(jìn)行排序時
經(jīng)常要用到某一列,則可以將該表在該列上聚集(物理排序),避免每次查詢該列時都進(jìn)行排序,
從而節(jié)省成本
非聚集索引
非聚集索引具有完全獨立于數(shù)據(jù)行的結(jié)構(gòu)。非聚集索引的最低行包含非聚集索引的鍵值,
并且每個鍵值項都有指針指向包含該鍵值的數(shù)據(jù)行。數(shù)據(jù)行不按基于非聚集鍵的次序存儲。
在非聚集索引內(nèi),從索引行指向數(shù)據(jù)行的指針稱為行定位器。
行定位器的結(jié)構(gòu)取決于數(shù)據(jù)頁的存儲方式是堆集還是聚集。對于堆集,行定位器是指向行的指針。
對于有聚集索引的表,行定位器是聚集索引鍵。
只有在表上創(chuàng)建了聚集索引時,表內(nèi)的行才按特定的順序存儲。這些行就基于聚集索引鍵按順序存儲。
如果一個表只有非聚集索引,它的數(shù)據(jù)行將按無序的堆集方式存儲
非聚集索引可以建多個,兩者都能改善查詢性能
非聚集索引與聚集索引一樣有 b 樹結(jié)構(gòu),但是有兩個重大差別:
數(shù)據(jù)行不按非聚集索引鍵的順序排序和存儲。
非聚集索引的葉層不包含數(shù)據(jù)頁。
相反,葉節(jié)點包含索引行。每個索引行包含非聚集鍵值以及一個或多個行定位器,
這些行定位器指向有該鍵值的數(shù)據(jù)行(如果索引不唯一,則可能是多行)。
非聚集索引可以在有聚集索引的表、堆集或索引視圖上定義
另外
唯一索引
唯一索引可以確保索引列不包含重復(fù)的值。在多列唯一索引的情況下,該索引可以確保索引列中每個值組
合都是唯一的。唯一索引既是索引也是約束。
復(fù)合索引
索引項是多個的就叫組合索引,也叫復(fù)合索引。復(fù)合索引使用時需要注意索引項的次序。
二 索引的創(chuàng)建
有兩種方法可以在 sql server 內(nèi)定義索引: create index 語句和create table 語句
create table支持在創(chuàng)建索引時使用下列約束:
primary key 創(chuàng)建唯一索引來強制執(zhí)行主鍵
unique 創(chuàng)建唯一索引
clustered 創(chuàng)建聚集索引
nonclustered 創(chuàng)建非聚集索引
注: 1 定義索引時,可以指定每列的數(shù)據(jù)是按升序還是降序存儲。如果不指定,則默認(rèn)為升序
2 支持在計算列上創(chuàng)建索引
3 為索引指定填充因子
可標(biāo)識填充因子來指定每個索引頁的填滿程度。索引頁上的空余空間量很重要,
因為當(dāng)索引頁填滿時,系統(tǒng)必須花時間拆分它以便為新行騰出空間。
三 索引的維護(hù)語句
dbcc dbreindex 重建指定數(shù)據(jù)庫中表的一個或多個索引
dbcc indexfrag 整理指定的表或視圖的聚集索引和輔助索引碎片
比較
速度 兼容性 日志影響 數(shù)據(jù)訪問影響 額外磁盤空間
dbcc 最快 最好 大,但能通過把 操作過程中數(shù)據(jù)不 需要大
dbreindex 可以重 故障還原模型設(shè) 能訪問,影響大
建所有 為簡單減少日志
有索引
dbcc 慢 但可 必須分 小 數(shù)據(jù)未被鎖定 需要小
indexdefrag 隨時終 別指定
止執(zhí)行
drop index 中等 必須分 大,但能通過把 僅在操作執(zhí)行時 中等,操作在
create index 別指定 故障還原模型設(shè) 鎖定數(shù)據(jù) tempdb中進(jìn)行
為簡單減少日志
四 查看索引的方法
sp_indexes 返回指定遠(yuǎn)程表的索引信息
indexkey_property 返回有關(guān)索引鍵的信息
sysindexes系統(tǒng)表 數(shù)據(jù)庫中的每個索引和表在表中各占一行,該表存儲在每個數(shù)據(jù)庫中
五 可以通過執(zhí)行計劃
查看sql語句執(zhí)行時是否建立在索引之上
比如
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
執(zhí)行計劃可以看出使用了ix_test索引
2 select * from test where field_1 =1
執(zhí)行計劃可以看出使用了pk_test
3 但如果是select * from test with (index(ix_test)) where field_1 =1
則指定使用索引
六 索引的具體使用 (轉(zhuǎn)貼)
1) 索引的設(shè)計
a:盡量避免表掃描
檢查你的查詢語句的where子句,因為這是優(yōu)化器重要關(guān)注的地方。包含在where里面的每一列(column)都是可能的侯選索引,為能達(dá)到最優(yōu)的性能,考慮在下面給出的例子:對于在where子句中給出了column1這個列。
下面的兩個條件可以提高索引的優(yōu)化查詢性能!
第一:在表中的column1列上有一個單索引
第二:在表中有多索引,但是column1是第一個索引的列
避免定義多索引而column1是第二個或后面的索引,這樣的索引不能優(yōu)化服務(wù)器性能
例如:下面的例子用了pubs數(shù)據(jù)庫。
select au_id, au_lname, au_fname from authors
where au_lname = ’white’
按下面幾個列上建立的索引將會是對優(yōu)化器有用的索引
?au_lname
?au_lname, au_fname
而在下面幾個列上建立的索引將不會對優(yōu)化器起到好的作用
?au_address
?au_fname, au_lname
考慮使用窄的索引在一個或兩個列上,窄索引比多索引和復(fù)合索引更能有效。用窄的索引,在每一頁上
將會有更多的行和更少的索引級別(相對與多索引和復(fù)合索引而言),這將推進(jìn)系統(tǒng)性能。
對于多列索引,sql server維持一個在所有列的索引上的密度統(tǒng)計(用于聯(lián)合)和在第一個索引上的
histogram(柱狀圖)統(tǒng)計。根據(jù)統(tǒng)計結(jié)果,如果在復(fù)合索引上的第一個索引很少被選擇使用,那么優(yōu)化器對很多查詢請求將不會使用索引。
有用的索引會提高select語句的性能,包括insert,uodate,delete。
但是,由于改變一個表的內(nèi)容,將會影響索引。每一個insert,update,delete語句將會使性能下降一些。實驗表明,不要在一個單表上用大量的索引,不要在共享的列上(指在多表中用了參考約束)使用重疊的索引。
在某一列上檢查唯一的數(shù)據(jù)的個數(shù),比較它與表中數(shù)據(jù)的行數(shù)做一個比較。這就是數(shù)據(jù)的選擇性,這比較結(jié)果將會幫助你決定是否將某一列作為侯選的索引列,如果需要,建哪一種索引。你可以用下面的查詢語句返回某一列的不同值的數(shù)目。
select count(distinct cloumn_name) from table_name
假設(shè)column_name是一個10000行的表,則看column_name返回值來決定是否應(yīng)該使用,及應(yīng)該使用什么索引。
unique values index
5000 nonclustered index
20 clustered index
3 no index
2) 鏃索引和非鏃索引的選擇
<1:>鏃索引是行的物理順序和索引的順序是一致的。頁級,低層等索引的各個級別上都包含實際的數(shù)據(jù)頁。一個表只能是有一個鏃索引。由于update,delete語句要求相對多一些的讀操作,因此鏃索引常常能加速這樣的操作。在至少有一個索引的表中,你應(yīng)該有一個鏃索引。
在下面的幾個情況下,你可以考慮用鏃索引:
例如: 某列包括的不同值的個數(shù)是有限的(但是不是極少的)
顧客表的州名列有50個左右的不同州名的縮寫值,可以使用鏃索引。
例如: 對返回一定范圍內(nèi)值的列可以使用鏃索引,比如用between,>,>=,<,<=等等來對列進(jìn)行操作的列上。
select * from sales where ord_date between ’5/1/93’ and ’6/1/93’
例如: 對查詢時返回大量結(jié)果的列可以使用鏃索引。
select * from phonebook where last_name = ’smith’
當(dāng)有大量的行正在被插入表中時,要避免在本表一個自然增長(例如,identity列)的列上建立鏃索引。如果你建立了鏃的索引,那么insert的性能就會大大降低。因為每一個插入的行必須到表的最后,表的最后一個數(shù)據(jù)頁。
當(dāng)一個數(shù)據(jù)正在被插入(這時這個數(shù)據(jù)頁是被鎖定的),所有的其他插入行必須等待直到當(dāng)前的插入已經(jīng)結(jié)束。
一個索引的葉級頁中包括實際的數(shù)據(jù)頁,并且在硬盤上的數(shù)據(jù)頁的次序是跟鏃索引的邏輯次序一樣的。
<2:>一個非鏃的索引就是行的物理次序與索引的次序是不同的。一個非鏃索引的葉級包含了指向行數(shù)據(jù)頁的指針。
在一個表中可以有多個非鏃索引,你可以在以下幾個情況下考慮使用非鏃索引。
在有很多不同值的列上可以考慮使用非鏃索引
例如:一個part_id列在一個part表中
select * from employee where emp_id = ’pcm9809f’
查詢語句中用order by 子句的列上可以考慮使用鏃索引
3) 一個表列如果設(shè)為主鍵(primary key),它會自動生成一個聚簇索引
這時不能直接使用drop index table1.tableindex1語句
必須刪除主鍵約束,用語句:alter table table1 drop constraint 約束名(如pk_xxx)
最后補充
全文索引請參考
http://expert.csdn.net/expert/topic/1594/1594455.xml?temp=.1432154
本文來源于網(wǎng)頁設(shè)計愛好者web開發(fā)社區(qū)http://www.html.org.cn收集整理,歡迎訪問。