Informix Dynamic Server分段存儲,也稱之為分片存儲,其原理是對資料表中的記錄或索引有規則地分散存儲在磁片不同的區域,達到將資料存儲在多個磁片上,通過減少對磁片I/O的競爭,來提高資料庫的效率。與此相反的是基本存放裝置原則,其鼓勵將資料庫表中的資料儘量連續地存放在一個存放裝置上,在Informix Dynamic Server讀出資料時,將資料批量讀出,以提高資料庫的效率。

 

分段存儲主要是通過均衡磁片 I/O,實現內部查詢的平行作業、並行地掃描多個磁片上的資料來提高查詢效率,其使資料庫性能的提高主要來自于I/O並行度的提高,而不是I/O性能的提高。實際上分段存儲是對一些資料量較大的表在存儲時提供的一個方法,使用者可以選擇分段存儲也可以不選擇分段存儲。一個好的分段存儲工具可以很好地提高查詢效率。否則,不但資料庫的查詢效率得不到提高反而會降低。在實際應用中,Informix Dynamic Server並不會在意資料放在哪個具體的物理盤上,而是具體到相應的dbspace上,因為Informix Dynamic Server查詢可併發執行的最小單位就是dbspace。

 

分段存儲的原理

 

分段存儲可以分為輪轉法和基於運算式的方法。輪轉法是使用Informix Dynamic Server內部定義的規則將表分段存儲。在建表時,可以指定對資料的存儲採用輪轉法,其語法是: CREATE TABLE tablename (aa integer ...)
FRAGMENT BY ROUND ROBIN IN dbspace1,dbspace2, ......dbspaceN。


 

基於運算式的方法是使用使用者定義的規則將表或索引分段存儲在不同的dbspace中。基於運算式的方法又可以分為範圍規則和絕對規則,範圍規則是用SQL的關係(>、<、>=、<=)或邏輯操作(and、or)定義表的資料分片的邊界,一般用一個欄位,也可以根據需要用2個或多個欄位。範圍規則的語法是: CREATE TABLE tablename (a1integer....)
FRAGMENT BY EXPRESSION
a1 <= 0 IN dbspace1,
a1 >= 0 AND a1 <= 100000 IN dbspace2,
REMAINDER IN dbspace3;


 

絕對規則是用關係操作符(>、<、>=、<=)與邏輯操作符(and、or)對規則進行定義,可以是表中的多個欄位參與分段。絕對規則的語法是: CREATE TABLE tablename (a1 integer....)
 FRAGMENT BY EXAMPLE
 a1 = 100000 or a1=200000 IN dbspace1,
 a1 = 300000 or a1=400000 IN dbspace2,
 REMAIDER IN dbspace3;


 

由於輪轉法採用的是Informix Dynamic Server內部定義的規則,所以在使用的過程中,比較簡單和方便。基於運算式的方法,使用的是使用者定義的規則,為了提高查詢效率,就要減輕CPU的負荷,均衡磁片的I/O操作。因此,使用者在使用運算式定義分段規則時,應該遵循以下原則:

 

1.要使運算式盡可能的簡單明瞭,避免在運算式中使用資料類型的轉換,以便在informix Dynamic Server寫入或讀出資料時盡可能快地解析運算式;

 

2.為了減少運算式的計算量,在運算式中應該把限制性最強的部分放在前面;

 

3.在分段運算式中要避免有經常更新的欄位,使得分段存儲的資料有一個相對固定的位置;

 

4.對所存儲的資料、查詢語句進行分析,明確查詢輸出的結果,使被頻繁訪問的資料能均衡地分佈在多個磁片上。

 

分段存儲設計的目標是為了給使用者提供更好的回應時間,更好的併發性,更好而且更快的備份和恢復,還具有較好的可用性。但是分段存儲無形中給資料庫增加了管理成本,而且資料庫的轉移也不太方便。為了達到這樣地目標,在對資料庫進行分段設計時,就要考慮主機的硬體特性,如CPU個數、速度、磁片的數目、磁碟控制卡的數目、每個磁碟控制卡連接的磁片數目等,及作業系統的性能。在硬體特性和作業系統性能滿足分段存儲時,可以對一些資料存儲量大的表進行分段存儲,這樣其性能將會有所提高。

 

分段存儲的實例

 

本文在對分段存儲的測試中,使用的是一台HP伺服器。該伺服器有4個較慢速的CPU,2GB記憶體,硬碟採用的是raid 5 技術。作業系統是 SCO Unix 5.0.6,資料庫是Informix 7.31uc5。在測試的過程中,機器基本閒置。使用onstat -d 命令輸出結果如下:

 

Informix Dynamic Server Version 7.31.UC5 -- On-Line -- Up 7 days 20:44:47 --

 

307200 Kbytes

 

Dbspaces

 

address number flags fchunk nchunks flags owner name

 

92c5413c 1 1 1 1 N informix rootdbs

 

92c54d94 2 1 2 1 N informix phydbs

 

92c54e50 3 1 3 1 N informix logdbs

 

92c54f0c 4 2001 4 1 N T informix tmpdbs

 

92c54fc8 5 1 5 7 N informix datadbs

 

92c55084 6 1001 12 1 N informix datatest1

 

92c55140 7 1001 13 1 N informix datatest2

 

7 active, 2047 maximum

 

Chunks

 

address chk/dbs offset size free bpages flags pathname

 

92c541f8 1 1 100 250000 146465 PO- /home/informix/DBS/rootdbs

 

92c54344 2 2 100 150000 4947 PO- /home/informix/DBS/phydbs

 

92c54420 3 3 100 500000 90347 PO- /home/informix/DBS/logdbs

 

92c544fc 4 4 100 500000 499947 PO- /home/informix/DBS/tmpdbs

 

……省去了datadbs使用的7個chunk

 

92c54bdc 12 6 50 950000 484235 PO- /home/informix/DBS/data_chunk7

 

92c54cb8 13 7 50 950000 420499 PO- /home/informix/DBS/data_chunk8

 

13 active, 2047 maximum
測試中使用的dbspace是datatest1和datatest2,其分別對應了data_chunk7和data_chunk8的兩個chunk。測試用的資料庫建立在datatest1中,在資料庫中有兩個表,表的名稱是dcc_saacnamt和dcc_saacnamt1,兩個表的結構一樣,存儲的資料一樣,記錄數都是148萬條,都沒有建立索引。
表dcc_saacnamt存儲在datatest2中,沒有採用分段存儲;表dcc_saacnamt1採用分段存儲,分別存儲在datatest1和datatest2中。首先採用基於運算式的範圍規則對dcc_saacnamt1進行分段存儲,建表的運算式為: create table dcc_saacnamt1 (
sa_acct_no char(28) not null ,
……
etl_load_date date )
FRAGMENT BY EXPRESSION
etl_load_date <= "20050630" and etl_load_date >= "20050101"
in datatest2,
etl_load_date <="20051231" and etl_load_date>="20050701"
in datatest1;
 
為了方便測試,將etl_load_date的取值定在2005年1月1日到2005年12月31日之間。
 
測試用shell如下: date >aa {輸出開始時間}
dbaccess -s testfrag<set explain on;{打開informix跟蹤器}
SET OPTIMIZATION FIRST_ROWS;{打開informix選擇最優的查詢路徑}
set pdqpriority high;{打開informix PDQ並行查詢開關}
drop table test_poll1;
create table test_poll1{建立測試用表}
(
sa_no char(28),
etl_date date
) in datatest1;
insert into test_poll1 (sa_no,etl_date)
select sa_acct_no,etl_load_date from dcc_saacnamt1 {從分段存儲表中讀取資料}
where (etl_load_date <= "20050630" and etl_load_date>= "20050101");
!
date >>aa{輸出分段存儲讀取資料結束時間}
dbaccess -s testfrag<set explain on;{打開informix跟蹤器}
SET OPTIMIZATION FIRST_ROWS; {打開informix選擇最優的查詢路徑}
set pdqpriority high;{打開informix PDQ並行查詢開關}
drop table test_poll;
create table test_poll{建立測試用表}
(
sa_no char(28),
etl_date date
) in datatest1;
insert into test_poll (sa_no,etl_date)
select sa_acct_no,etl_load_date from dcc_saacnamt {從非分段存儲表中讀取資料}
where (etl_load_date <= "20050630" and etl_load_date>= "20050101");
!
date >>aa{輸出結束時間}
 
檔aa記錄的結果:
 
Fri Feb 24 09:47:23 CST 2006
 
Fri Feb 24 09:47:29 CST 2006
 
Fri Feb 24 09:48:13 CST 2006
 
可以看出採用分段存儲,讀取資料及寫表使用了6秒的時間,不分段存儲使用了44秒的時間。
 
在對Informix跟蹤器輸出的sqexplain.out檔進行分析,發現在從dcc_saacnamt1表中讀取資料時,由於表dcc_saacnamt1採用了分段存儲,所以在讀取和寫入資料時,採用了平行作業。對沒有分段存儲的表dcc_saacnamt的查詢只是一般的掃描操作。sqexplain.out檔結果如下: QUERY: {表分段存儲後查詢資料時Informix跟蹤結果}
insert into test_poll1 (sa_no,etl_date)
select sa_acct_no,etl_load_date from dcc_saacnamt1
where (etl_load_date <= "20050630" and etl_load_date>= "20050101")
Estimated Cost: 2
Estimated # of Rows Returned: 11
Maximum Threads: 1
1) brow.dcc_saacnamt1: SEQUENTIAL SCAN (Parallel, fragments: 0)
Filters: (brow.dcc_saacnamt1.etl_load_date <= 2005/06/30 AND brow.dcc_saacna
mt1.etl_load_date >= 2005/01/01 )
QUERY: {表非分段存儲後查詢資料時Informix跟蹤結果}
......
insert into test_poll (sa_no,etl_date)
select sa_acct_no,etl_load_date from dcc_saacnamt
where (etl_load_date <= "20050630" and etl_load_date>= "20050101")
Estimated Cost: 2
Estimated # of Rows Returned: 111204
Maximum Threads: 1
1) brow.dcc_saacnamt: SEQUENTIAL SCAN
Filters: (brow.dcc_saacnamt.etl_load_date <= 2005/06/30 AND brow.dcc_saacnam
t.etl_load_date >= 2005/01/01 )
 
在使用輪轉法對dcc_saacnamt1進行分段存儲,也採用相同的測試方法,結果基本一致,但是效果沒有基於運算式的方法好。
 
綜上所述,分段存儲能提高資料庫的效率,是資料庫查詢優化方法之一,但是它也有一定的缺陷。在對資料庫進行查詢優化時,可以使用分段存儲。但不能對資料庫中所有的表都實行分段存儲,而是要有選擇的進行。
arrow
arrow
    全站熱搜

    戮克 發表在 痞客邦 留言(0) 人氣()