如果查詢結果僅為一行或很少幾行時(高選擇性high selectivity),利用索引進行查詢會大大提高效率。相比之下,如果沒有索引,查詢則只能順序掃描整個表。在OLTP環(huán)境下,事務處理在很大程度上依賴于索引。只有在表很小時,才會順序掃描表。系統(tǒng)會根據(jù)SQL語句中的WHERE子句判斷是否使用索引。順序掃描表會使系統(tǒng)性能受到嚴重影響。sysmaster中sysptntab表中的pf_seqscnas列顯示了所進行的順序掃描。SET EXPLAIN命令同樣可以提供關于SQL語句如何訪問數(shù)據(jù)庫中的重要信息。
DSS環(huán)境中的應用經(jīng)常會查詢出大量數(shù)據(jù)(低選擇性 low selecviity),甚至整張表。順序掃描對于這樣的查詢更為適合,因為此時順序掃描可以利用light scan。light scan緩沖區(qū)位于共享內(nèi)存的虛擬段與駐留段無關。關于light scan,以后章節(jié)中還將詳述。
建立索引的代價
雖然索引可以很大地提高高選擇性查詢的性能,但維護這些索引是需要付出代價的。 以INSERT語句為例,在進行插入時系統(tǒng)首先將讀取被插入表的索引以定位新記錄關鍵字的位置。然后系統(tǒng)在將新記錄寫入數(shù)據(jù)頁的同時還必須將新索引項寫入索引節(jié)點。如果導致索引節(jié)點分裂,系統(tǒng)則必須多次寫索引頁 。
與INSERT語句相似,DELETE語句也要求讀入整個索引以定位索引節(jié)點位置,并置上刪除標志。在刪除索引時還需要處理索引節(jié)點合并、整理等問題。
在執(zhí)行UPDATE語句時,必須首先定位并且刪除舊的關鍵字然后插入新的關鍵字。所以在UPDATE語句必須兩次讀取索引。
在實際系統(tǒng)中通常把索引的根節(jié)點和第一級節(jié)點讀入共享內(nèi)存中,但如果需要訪問更低層次的索引節(jié)點則必須進行磁盤操作。
索引類型
通常建立分離索引(detached)或基于表達式的索引分片(expression based fragmented)。分離索引和分片索引可以使得索引的extent內(nèi)頁連續(xù),因而能提高性能。而對于不分片的表來說,附加索引(attached)在建立索引時,索引頁和數(shù)據(jù)頁交叉存放在一起,因而會增加磁頭尋找時間。
對于中、小型表應該建立分離索引。對于經(jīng)常訪問的大表應建立基于表達式的分片索引,以減少索引頁的數(shù)量和提高檢索速度。索引分片不宜太多,以免表達式計算開銷過大。根據(jù)索引的大小,一般可以分為4片。索引分片不支持輪轉(zhuǎn)法(round robin)。
分離式索引與數(shù)據(jù)頁分別存放在不同的數(shù)據(jù)空間中。
例如:
CREATE INDEX index1 ON TABLE table_name(col1) in idxldbs;
基于表達式的分片索引在FRAGMENT BY EXPRESSION 子句指定的數(shù)據(jù)空間中創(chuàng)建。
例如:
CREATE INDEX index1 on TABLE table_name(col1) FRAGMENT BY EXPRESSION
col1>=0 and col1<=25000 in idxldbs1 col1>=25001 and col1<=50000 in idxldbs2
col1>=50001 and col1<=75000 in idxldbs3 col1>=750001 and col1<= 100000 in idxldbs4;
隱式索引
在定義約束條件時如果沒有可利用的索引,系統(tǒng)將創(chuàng)建隱式索引。用戶不能對隱式索引指定數(shù)據(jù)空間的位置、分片策略或者填充因子。隱式索引創(chuàng)建在數(shù)據(jù)庫(而非表)所在地數(shù)據(jù)空間中,這給磁盤管理和性能帶來了一些影響。
用戶如果需要建立約束條件,能先創(chuàng)建與約束條件完全匹配的顯式索引然后用ALTER TABLE命令增加約束條件。這樣該約束條件就可以利用顯式索引而不必再建立隱式索引。
例如按如下方式:
CREATE TABLE table_name( col1 INTEGER, col2 INTEGER, col3 CHAR(25), ) in tableldbs;
CREATE unique INDEX index1 ON TABLE table_name(col1) in idxldbs;
ALTER TABLE table_name ADD CONSTRAINT PRIMARYKEY(col1);
而不要按如下方式:
CREATE TABLE table_name( col1 INTEGER, col2 INTEGER, col3 CHAR(25), PRIMARY KEY (col1) )
in tableldbs;
FILLACTOR(填充因子)
對于SELECT操作,將FILLFACTOR 設為100
對于SELECT 和DELETE操作將FILLFACTOR 設為100
對于INSERT 和 UPDATE操作將FILLFACTOR設為50到70
CREATE INDEX index1 ON TABLE table_name(col1) in idx1 dbs FILLFACTOR 70;
填充因子決定了在建立索引時每一索引頁的填充度。該參數(shù)是可以改變的。參數(shù)FILLFACTOR缺省值為90。如果只是改變某個索引的設置,請使用CREATE INDEX的FILLFACTOR子句。
設置較大的填充因子可以使索引更緊湊、使緩沖區(qū)更有效同時也可以減少檢索記錄時讀取的頁數(shù)。對于只讀表應將FILLFACTOR設置為100。
對于只執(zhí)行讀和操作的表,如果將FILLFACTOR設置為100,在刪除記錄時可以減少合并索引節(jié)點、整理索引樹的可能性。
對于有大量插入和更新操作的表,應該將FILLFACTOR設置為50到70。由于填充因子較小,在插入和更新操作時將延遲索引節(jié)點(頁面)的分裂,從而提高系統(tǒng)性能。
有如下的SQL FILLFACTOR例句:
CREATE INDEX index1 ON TABLE table_name(col1) in idxldbs FILLFACTOR 70;
建立索引的步驟
建立索引必須遵循如下步驟:
確定需要建立的索引
決定索引的類型,分離索引還是分片索引。如果是分片索引,確定表達式
為每一索引確定填充因子
計算索引所需空間
決定索引數(shù)據(jù)空間在磁盤上的位置
為索引創(chuàng)建數(shù)據(jù)空間
定髓臨時數(shù)據(jù)空間大小和位置。臨時數(shù)據(jù)空間能分布存儲。
利用DBSPACETEMP 設置臨時數(shù)據(jù)空間的大小,利用onspace命令的-t選項創(chuàng)建臨時數(shù)據(jù)空間
設置環(huán)境變量PDQPRIORITY 和PSORT_NPROCS
創(chuàng)建相應的配置文件。其中各選項的設置參見并行排序和載入環(huán)境
配置參數(shù)
建立索引時參數(shù)的優(yōu)化設置與上一章載入環(huán)境中的設置相同。在此作一簡單回顧:
NUMCPUVPS 設置為CPU數(shù)目
BUFFERS 設置盡量多的緩沖區(qū)。初始時應為緩沖區(qū)分配最多至25%的內(nèi)存。
SHMVIRTSIZE 賦予初始段值。最多至可用內(nèi)存的75%
CKPTINTVL 3000。由物理日志決定何時生成檢查點。
LRUS 一個LRU隊列對含500-700個緩沖并允許LRU隊列對至128
LUR_MAX_DIRTY 設置為80
LUR_MIN_dirty 設置為70
RA_PAGES 設置為128,
RA_THRESHOLD 設置為120
DBSPACETEMP 設置多個大小相同的臨時數(shù)據(jù)空間分布在不同的設備上
DS_TOTAL_MEMORY 90%*SHMVIRTSIZE
DS_MAX_SCANS 待建索引表的分片數(shù)
下面是對環(huán)境變量的簡單回顧:
PSORT_NPROCS 設置為CPU數(shù)目,至10
PDQPRIORITY 設置為100
數(shù)據(jù)聚集
如果經(jīng)常根據(jù)索引從表中讀取大量的數(shù)據(jù),那么對這些數(shù)據(jù)建立聚集。通過建立聚集可以減少讀取頁的數(shù)量,縮短檢索時間,并可以充分利用預讀功能順序掃描數(shù)據(jù)。
數(shù)據(jù)的聚集通過創(chuàng)建聚集索引(clustered index)完成。利用ALTER INDEX ...TO CLUSTER 語句可以將原有索引改為聚集索引,原有索引中的數(shù)據(jù)記錄順序?qū)⒆髦嘏?。如果直接?chuàng)建聚集索引,系統(tǒng)也會將數(shù)據(jù)記錄排序。請注意,在ATLTER INDEX ...TO CLUSTER 和CREATE CLUSTER INDEX 語句執(zhí)行后,系統(tǒng)將建立新表并刪除舊表。所以必須有足夠的空間來容納新舊兩張表。
如果可能,在載入數(shù)據(jù)前先對其按索引順序排序,這樣建立索引時不必設置CLUSTER子句,從而不必對數(shù)據(jù)進行聚集操作,避免建新表刪舊表過程的開銷。
DSS環(huán)境中的應用經(jīng)常會查詢出大量數(shù)據(jù)(低選擇性 low selecviity),甚至整張表。順序掃描對于這樣的查詢更為適合,因為此時順序掃描可以利用light scan。light scan緩沖區(qū)位于共享內(nèi)存的虛擬段與駐留段無關。關于light scan,以后章節(jié)中還將詳述。
建立索引的代價
雖然索引可以很大地提高高選擇性查詢的性能,但維護這些索引是需要付出代價的。 以INSERT語句為例,在進行插入時系統(tǒng)首先將讀取被插入表的索引以定位新記錄關鍵字的位置。然后系統(tǒng)在將新記錄寫入數(shù)據(jù)頁的同時還必須將新索引項寫入索引節(jié)點。如果導致索引節(jié)點分裂,系統(tǒng)則必須多次寫索引頁 。
與INSERT語句相似,DELETE語句也要求讀入整個索引以定位索引節(jié)點位置,并置上刪除標志。在刪除索引時還需要處理索引節(jié)點合并、整理等問題。
在執(zhí)行UPDATE語句時,必須首先定位并且刪除舊的關鍵字然后插入新的關鍵字。所以在UPDATE語句必須兩次讀取索引。
在實際系統(tǒng)中通常把索引的根節(jié)點和第一級節(jié)點讀入共享內(nèi)存中,但如果需要訪問更低層次的索引節(jié)點則必須進行磁盤操作。
索引類型
通常建立分離索引(detached)或基于表達式的索引分片(expression based fragmented)。分離索引和分片索引可以使得索引的extent內(nèi)頁連續(xù),因而能提高性能。而對于不分片的表來說,附加索引(attached)在建立索引時,索引頁和數(shù)據(jù)頁交叉存放在一起,因而會增加磁頭尋找時間。
對于中、小型表應該建立分離索引。對于經(jīng)常訪問的大表應建立基于表達式的分片索引,以減少索引頁的數(shù)量和提高檢索速度。索引分片不宜太多,以免表達式計算開銷過大。根據(jù)索引的大小,一般可以分為4片。索引分片不支持輪轉(zhuǎn)法(round robin)。
分離式索引與數(shù)據(jù)頁分別存放在不同的數(shù)據(jù)空間中。
例如:
CREATE INDEX index1 ON TABLE table_name(col1) in idxldbs;
基于表達式的分片索引在FRAGMENT BY EXPRESSION 子句指定的數(shù)據(jù)空間中創(chuàng)建。
例如:
CREATE INDEX index1 on TABLE table_name(col1) FRAGMENT BY EXPRESSION
col1>=0 and col1<=25000 in idxldbs1 col1>=25001 and col1<=50000 in idxldbs2
col1>=50001 and col1<=75000 in idxldbs3 col1>=750001 and col1<= 100000 in idxldbs4;
隱式索引
在定義約束條件時如果沒有可利用的索引,系統(tǒng)將創(chuàng)建隱式索引。用戶不能對隱式索引指定數(shù)據(jù)空間的位置、分片策略或者填充因子。隱式索引創(chuàng)建在數(shù)據(jù)庫(而非表)所在地數(shù)據(jù)空間中,這給磁盤管理和性能帶來了一些影響。
用戶如果需要建立約束條件,能先創(chuàng)建與約束條件完全匹配的顯式索引然后用ALTER TABLE命令增加約束條件。這樣該約束條件就可以利用顯式索引而不必再建立隱式索引。
例如按如下方式:
CREATE TABLE table_name( col1 INTEGER, col2 INTEGER, col3 CHAR(25), ) in tableldbs;
CREATE unique INDEX index1 ON TABLE table_name(col1) in idxldbs;
ALTER TABLE table_name ADD CONSTRAINT PRIMARYKEY(col1);
而不要按如下方式:
CREATE TABLE table_name( col1 INTEGER, col2 INTEGER, col3 CHAR(25), PRIMARY KEY (col1) )
in tableldbs;
FILLACTOR(填充因子)
對于SELECT操作,將FILLFACTOR 設為100
對于SELECT 和DELETE操作將FILLFACTOR 設為100
對于INSERT 和 UPDATE操作將FILLFACTOR設為50到70
CREATE INDEX index1 ON TABLE table_name(col1) in idx1 dbs FILLFACTOR 70;
填充因子決定了在建立索引時每一索引頁的填充度。該參數(shù)是可以改變的。參數(shù)FILLFACTOR缺省值為90。如果只是改變某個索引的設置,請使用CREATE INDEX的FILLFACTOR子句。
設置較大的填充因子可以使索引更緊湊、使緩沖區(qū)更有效同時也可以減少檢索記錄時讀取的頁數(shù)。對于只讀表應將FILLFACTOR設置為100。
對于只執(zhí)行讀和操作的表,如果將FILLFACTOR設置為100,在刪除記錄時可以減少合并索引節(jié)點、整理索引樹的可能性。
對于有大量插入和更新操作的表,應該將FILLFACTOR設置為50到70。由于填充因子較小,在插入和更新操作時將延遲索引節(jié)點(頁面)的分裂,從而提高系統(tǒng)性能。
有如下的SQL FILLFACTOR例句:
CREATE INDEX index1 ON TABLE table_name(col1) in idxldbs FILLFACTOR 70;
建立索引的步驟
建立索引必須遵循如下步驟:
確定需要建立的索引
決定索引的類型,分離索引還是分片索引。如果是分片索引,確定表達式
為每一索引確定填充因子
計算索引所需空間
決定索引數(shù)據(jù)空間在磁盤上的位置
為索引創(chuàng)建數(shù)據(jù)空間
定髓臨時數(shù)據(jù)空間大小和位置。臨時數(shù)據(jù)空間能分布存儲。
利用DBSPACETEMP 設置臨時數(shù)據(jù)空間的大小,利用onspace命令的-t選項創(chuàng)建臨時數(shù)據(jù)空間
設置環(huán)境變量PDQPRIORITY 和PSORT_NPROCS
創(chuàng)建相應的配置文件。其中各選項的設置參見并行排序和載入環(huán)境
配置參數(shù)
建立索引時參數(shù)的優(yōu)化設置與上一章載入環(huán)境中的設置相同。在此作一簡單回顧:
NUMCPUVPS 設置為CPU數(shù)目
BUFFERS 設置盡量多的緩沖區(qū)。初始時應為緩沖區(qū)分配最多至25%的內(nèi)存。
SHMVIRTSIZE 賦予初始段值。最多至可用內(nèi)存的75%
CKPTINTVL 3000。由物理日志決定何時生成檢查點。
LRUS 一個LRU隊列對含500-700個緩沖并允許LRU隊列對至128
LUR_MAX_DIRTY 設置為80
LUR_MIN_dirty 設置為70
RA_PAGES 設置為128,
RA_THRESHOLD 設置為120
DBSPACETEMP 設置多個大小相同的臨時數(shù)據(jù)空間分布在不同的設備上
DS_TOTAL_MEMORY 90%*SHMVIRTSIZE
DS_MAX_SCANS 待建索引表的分片數(shù)
下面是對環(huán)境變量的簡單回顧:
PSORT_NPROCS 設置為CPU數(shù)目,至10
PDQPRIORITY 設置為100
數(shù)據(jù)聚集
如果經(jīng)常根據(jù)索引從表中讀取大量的數(shù)據(jù),那么對這些數(shù)據(jù)建立聚集。通過建立聚集可以減少讀取頁的數(shù)量,縮短檢索時間,并可以充分利用預讀功能順序掃描數(shù)據(jù)。
數(shù)據(jù)的聚集通過創(chuàng)建聚集索引(clustered index)完成。利用ALTER INDEX ...TO CLUSTER 語句可以將原有索引改為聚集索引,原有索引中的數(shù)據(jù)記錄順序?qū)⒆髦嘏?。如果直接?chuàng)建聚集索引,系統(tǒng)也會將數(shù)據(jù)記錄排序。請注意,在ATLTER INDEX ...TO CLUSTER 和CREATE CLUSTER INDEX 語句執(zhí)行后,系統(tǒng)將建立新表并刪除舊表。所以必須有足夠的空間來容納新舊兩張表。
如果可能,在載入數(shù)據(jù)前先對其按索引順序排序,這樣建立索引時不必設置CLUSTER子句,從而不必對數(shù)據(jù)進行聚集操作,避免建新表刪舊表過程的開銷。