索引的應用規律總結

kitesky發表於2005-06-06

建立正確的索引,是提高系統效能的有效方法。正確的索引可能使查詢效率提高1000倍,而無效的索引可能是浪費了資料庫空間,甚至大大降低查詢效能。

索引的效果是和檢索資料的SQL語句、資料庫的繁忙程度、資料庫空間大小相關的,當資料庫效能下降,需要透過調整索引達到提高效能的時候,DBA應該充分考慮到影響索引效能的這些因素來重新構造索引。合理的索引設計要建立在對各種查詢的分析和預測上。

[@more@]

一、索引的管理成本

1、 儲存索引的磁碟空間
2、 執行資料修改操作(INSERT、UPDATE、DELETE)產生的索引維護
3、 在資料處理時回需額外的回退空間。

實際資料修改測試:

一個表有欄位A、B、C,同時進行插入10000行記錄測試
在沒有建索引時平均完成時間是2.9秒
在對A欄位建索引後平均完成時間是6.7秒
在對A欄位和B欄位建索引後平均完成時間是10.3秒
在對A欄位、B欄位和C欄位都建索引後平均完成時間是11.7秒
從以上測試結果可以明顯看出索引對資料修改產生的影響


二、索引分類
<1> 索引按內部結構分類

1、B*樹索引
B*樹索引是最常用的索引,其儲存結構類似書的索引結構,有分支和葉兩種型別的儲存資料塊,分支塊相當於書的大目錄,葉塊相當於索引到的具體的書頁。一般索引及唯一約束索引都使用B*樹索引。

2、點陣圖索引
點陣圖索引儲存主要用來節省空間,減少ORACLE對資料塊的訪問,它採用點陣圖偏移方式來與表的行ID號對應,採用點陣圖索引一般是重複值太多的表欄位。點陣圖索引在實際密集型OLTP(資料事務處理)中用得比較少,因為OLTP會對錶進行大量的刪除、修改、新建操作,ORACLE每次進行操作都會對要操作的資料塊加鎖,所以多人操作很容易產生資料塊鎖等待甚至死鎖現象。在OLAP(資料分析處理)中應用點陣圖有優勢,因為OLAP中大部分是對資料庫的查詢操作,而且一般採用資料倉儲技術,所以大量資料採用點陣圖索引節省空間比較明顯。

<2> 索引按功能分類

1、唯一索引
唯一索引有兩個作用,一個是資料約束,一個是資料索引,其中資料約束主要用來保證資料的完整性,唯一索引產生的索引記錄中每一條記錄都對應一個唯一的ROWID。

2、主鍵索引
主關鍵字索引產生的索引同唯一索引,只不過它是在資料庫建立主關鍵字時系統自動建立的。

3、一般索引
一般索引不產生資料約束作用,其功能主要是對欄位建立索引表,以提高資料查詢速度。

<3> 索引按索引物件分類

1、單列索引:表單個欄位的索引
2、多列索引:也稱“組合索引”,表多個欄位的索引
3、函式索引:對欄位進行函式運算的索引

建立函式索引的方法:(以Oracle函式為例)

create index IDX_PAY_DATE on TAB_PAY_LIST(TRUNC(COL_DATE))
create index IDX_CLIENT_ID on TAB_BANK_CLIENT(MONEY_CODE || CLIENT_ID)
在對函式進行了索引後,如果當前會話要引用,應設定當前會話的query_rewrite_enabled為TRUE。
alter session set query_rewrite_enabled=true
注:如果對使用者函式進行索引的話,那使用者函式應加上deterministic引數,意思是函式在輸入值固定的情況下返回值也固定。例:
create or replace function trunc_add(input_date date)return date deterministic
as
begin
return trunc(input_date+1);
end trunc_add;

三、應用索引的掃描分類

1、INDEX UNIQUE SCAN(按索引唯一值掃描)
select * from zl_yhjbqk where hbs_bh=’5420016000’
2、INDEX RANGE SCAN(按索引值範圍掃描)
select * from zl_yhjbqk where hbs_bh>’5420016000’
select * from zl_yhjbqk where qc_bh>’7001’
3、INDEX FAST FULL SCAN(按索引值快速全部掃描)
select hbs_bh from zl_yhjbqk order by hbs_bh
select count(*) from zl_yhjbqk
select qc_bh from zl_yhjbqk group by qc_bh

四、建議建立索引的情況

1、表的主關鍵字
自動建立唯一索引
如zl_yhjbqk(使用者基本情況)中的hbs_bh(戶標識編號)

2、表的欄位唯一約束
ORACLE利用索引來保證資料的完整性
如lc_hj(流程環節)中的lc_bh+hj_sx(流程編號+環節順序)

3、直接條件查詢的欄位
在SQL中用於條件約束的欄位
如zl_yhjbqk(使用者基本情況)中的qc_bh(區冊編號)
select * from zl_yhjbqk where qc_bh=’춗甼曀ॄ꺠ॄ>7001’

4、查詢中與其它表關聯的欄位
欄位常常建立了外來鍵關係
如zl_ydcf(用電成份)中的jldb_bh(計量點表編號)
select * from zl_ydcf a,zl_yhdb b where a.jldb_bh=b.jldb_bh and b.jldb_bh=’540100214511’

5、查詢中排序的欄位
排序的欄位如果透過索引去訪問那將大大提高排序速度
select * from zl_yhjbqk order by qc_bh(建立qc_bh索引)
select * from zl_yhjbqk where qc_bh=’7001’ order by cb_sx(建立qc_bh+cb_sx索引,注:只是一個索引,其中包括qc_bh和cb_sx欄位)

6、查詢中統計或分組統計的欄位
select max(hbs_bh) from zl_yhjbqk
select qc_bh,count(*) from zl_yhjbqk group by qc_bh

五、不建議建立索引或少建索引的情況

1、表記錄很少
如果一個表只有5條記錄,採用索引去訪問記錄的話,那首先需訪問索引表,再透過索引表訪問資料表,一般索引表與資料表不在同一個資料塊,這種情況下ORACLE至少要往返讀取資料塊兩次。而不用索引的情況下ORACLE會將所有的資料一次讀出,處理速度顯然會比用索引快。

如表zl_sybm(使用部門)一般只有幾條記錄,除了主關鍵字外對任何一個欄位建索引都不會產生效能最佳化,實際上如果對這個表進行了統計分析後ORACLE也不會用你建的索引,而是自動執行全表訪問。如:
select * from zl_sybm where sydw_bh=’5401’(對sydw_bh建立索引不會產生效能最佳化)

2、經常插入、刪除、修改的表
對一些經常處理的業務表應在查詢允許的情況下儘量減少索引,如zl_yhbm,gc_dfss,gc_dfys,gc_fpdy等業務表。

3、資料重複且分佈平均的表欄位
假如一個表有10萬行記錄,有一個欄位A只有T和F兩種值,且每個值的分佈機率大約為50%,那麼對這種表A欄位建索引一般不會提高資料庫的查詢速度。

4、經常和主欄位一塊查詢但主欄位索引值比較多的表欄位
如gc_dfss(電費實收)表經常按收費序號、戶標識編號、抄表日期、電費發生年月、操作標誌來具體查詢某一筆收款的情況,如果將所有的欄位都建在一個索引裡那將會增加資料的修改、插入、刪除時間,從實際上分析一筆收款如果按收費序號索引就已經將記錄減少到只有幾條,如果再按後面的幾個欄位索引查詢將對效能不產生太大的影響。

六、什麼是組合索引和索引覆蓋的查詢

如何只透過索引返回結果

一個索引一般包括單個或多個欄位,如果能不訪問表直接應用索引就返回結果那將大大提高資料庫查詢的效能。對比以下三個SQL,其中對錶zl_yhjbqk的hbs_bh和qc_bh欄位建立了索引:
1 select hbs_bh,qc_bh,xh_bz from zl_yhjbqk where qc_bh=’7001’

執行路徑:
SELECT STATEMENT, GOAL = CHOOSE 11 265 5565
TABLE ACCESS BY INDEX ROWID DLYX ZL_YHJBQK 11 265 5565
INDEX RANGE SCAN DLYX 區冊索引 1 265
平均執行時間(0.078秒)
2 select hbs_bh,qc_bh from zl_yhjbqk where qc_bh=’7001’
執行路徑:
SELECT STATEMENT, GOAL = CHOOSE 11 265 3710
TABLE ACCESS BY INDEX ROWID DLYX ZL_YHJBQK 11 265 3710
INDEX RANGE SCAN DLYX 區冊索引 1 265
平均執行時間(0.078秒)
3 select qc_bh from zl_yhjbqk where qc_bh=’7001’
執行路徑:
SELECT STATEMENT, GOAL = CHOOSE 1 265 1060
INDEX RANGE SCAN DLYX 區冊索引 1 265 1060
平均執行時間(0.062秒)

從執行結果可以看出第三條SQL的效率最高。執行路徑可以看出第1、2條SQL都多執行了TABLE ACCESS BY INDEX ROWID(透過ROWID訪問表) 這個步驟,因為返回的結果列中包括當前使用索引(qc_bh)中未索引的列(hbs_bh,xh_bz),而第3條SQL直接透過QC_BH返回了結果,這就是透過索引直接返回結果的方法。

一般來說:

  ①.有大量重複值、且經常有範圍查詢(between, >,< ,>=,< =)和order by

  、group by發生的列,可考慮建立群集索引

  ②.經常同時存取多列,且每列都含有重複值可考慮建立組合索引

  ③.組合索引要儘量使關鍵查詢形成索引覆蓋,其前導列一定是使用最頻繁的列。

七、Oracle中的索引技術

<1> Oracle中如何重建索引

alter index 表電量結果表主鍵 rebuild

<2> Oracle中如何快速新建大資料量表的索引

如果一個表的記錄達到100萬以上的話,要對其中一個欄位建索引可能要花很長的時間,甚至導致伺服器資料庫當機,因為在建索引的時候ORACLE要將索引欄位所有的內容取出並進行全面排序,資料量大的話可能導致伺服器排序記憶體不足而引用磁碟交換空間進行,這將嚴重影響伺服器資料庫的工作。解決方法是增大資料庫啟動初始化中的排序記憶體引數,如果要進行大量的索引修改可以設定10M以上的排序記憶體(ORACLE預設大小為64K),在索引建立完成後應將引數修改回來,因為在實際OLTP資料庫應用中一般不會用到這麼大的排序記憶體。

八、SQL Server中索引技術
<1> SQL Server中如何使用索引最佳化器
<2> SQL Server中在檢視上建索引
<3> SQL Server中在計算列上建索引

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/66009/viewspace-799716/,如需轉載,請註明出處,否則將追究法律責任。

相關文章