Chinaunix首页 | 论坛 | 博客
  • 博客访问: 302821
  • 博文数量: 94
  • 博客积分: 2220
  • 博客等级: 大尉
  • 技术积分: 975
  • 用 户 组: 普通用户
  • 注册时间: 2004-12-17 21:17
文章分类

全部博文(94)

文章存档

2011年(5)

2010年(11)

2009年(1)

2008年(2)

2006年(1)

2005年(65)

2004年(9)

我的朋友

分类: DB2/Informix

2005-07-11 10:52:50

 Informix 高级培训教材(三)

3.6. 关于语句写法 
语句的效率与SQL 语句的写法有很大关系。在几种写法中选择一个合适的写法相当重要,有时效率会急剧提高。因此,在效率有问题的地方多检查自己语句的写法,有可能会取得重大突破。以下是一些实例:
(1).
在保单表中查找003”险种的0101”区站的数据
select * from rta1 where bm_cert[1,7]=”0030101”
该语句运行前设置set explain on,运行后查看sqexplain.out 结果如下:
QUERY:
select * from rta1 
where bm_cert[1,7]="0030107" 
Estimated Cost: 1
Estimated # of Rows Returned: 1 
1) hsx.rta1: INDEX PATH 8
(1) Index Keys: bm_cert 
Lower Index Filter: hsx.rta1.bm_cert[1,7] = '0030107' 
显示的搜索路径为索引路径,但实际上效率很低。现改为如下写法:
select * from rta1 where bm_cert > = ”00301010000000000000” 
and bm_cert<=”00301019999999999999”
该语句运行前设置set explain on,运行后查看sqexplain.out 结果如下: 
QUERY: 
select * from rta1 where bm_cert >= "003010100000000" 
and bm_cert<=”00301019999999999999” 
Estimated Cost: 1
Estimated # of Rows Returned: 3
1) hsx.rta1: INDEX PATH 
(1) Index Keys: bm_cert 
Lower Index Filter: hsx.rta1.bm_cert >= '003010100000000' 
显示与第一个写法无明显差别,实际上第二种写法效率远远高于第一种。实际测试第一种写法的时间需要41 秒而第二种写法的执行时间只需14 秒。 

因此, 程序中最好不要使用bm_cert[x,y]=”???” 这种形式, 而改为 bm_cert>=”???” 这种形式。
(2). 在程序中,我们经常做这样的工作,先判断表内是否有该条数据,如果有就 update 该条数据,否则就插入一条。一般都写成如下形式:
select .. from . where key=t_key 
if status=notfound then 
insert into .. 
else 
update .. 
end if 
实际上,写成如下形式效率更高 
update . where key=t_key 
if status=0 and sqlca.sqlerrd[3]=0 then 
insert into ..
end if 
因为当该条数据存在时,只做一次写操作。 
(3). 在应用系统中有这样一条SQL 语句。 
select print_name from validate_item 
where (acc_book_type = t_acc_book_type 
and acc_book_code = t_acc_book_code 
and 
center_code = t_center_code or center_code=”000000”
and item_code = t_item_code 
and direction_idx = t_dir_idx_val1 
and direction_other = t_dir_oth_val1) 
( validate_item 
表中acc_book_type , acc_book_code , center_code , item_code , direction_idx , direction_other  为唯一索引该语句的效率不高,改写为以下形式后效率得到了很大提高。在存储过程中,上面的写法此存储过程执行需用时分多钟,改为下面的写法后,用 时仅需.
select print_name 
into t_str 
from validate_item 
where (acc_book_type = t_acc_book_type 
and acc_book_code = t_acc_book_code 
and center_code = t_center_code 
and item_code = t_item_code 
and direction_idx = t_dir_idx_val1
and direction_other = t_dir_oth_val1) 
or (acc_book_type = t_acc_book_type 
and acc_book_code = t_acc_book_code
and center_code = "000000" 
and item_code = t_item_code 
and direction_idx = t_dir_idx_val1 
and direction_other = t_dir_oth_val1); 
SQL 语句中,where 条件中有or 的语句,where 条件尽量用大组合,而不要用小组合。 

3.7. 
关于使用put , execute 来代替insert 提高效率在做数据转换或登录大批量数据时,用put execute 替代insert ,将使效率大幅度提高。因为在循环体内,减少了对insert 的语法检查及预处理的时间。 
Put 的用法如下:
let t_pre_1 = "insert into rta1 value"
"(?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?)" 
prepare pre_rta1_1 from t_pre_1
declare cur_ins_1 cursor for pre_rta1_1 
open cur_ins_1
循环体(while , for , foreach) 

put cur_ins_1 from p_rta1.* 

close cur_ins_1 
execute 
的语法如下: 
let t_pre_1 = "insert into rta1 value"
"(?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?)" 
prepare pre_rta1_1 from t_pre_1 
循环体(while , for , foreach)

execute pre_rta1_1 using p_rta1.* 

使用put 必须注意以下内容:
u put 
语句必须在事物中。 
u put 语句执行完后,马上从库中select 不一定能取到数
3.8. 
使用隔离级别(isolation 
共有四种隔离级别 
Dirty read 
Commited read 
Cursor stability 
Repeatable read 
<
> dirty read 
可能读到未提交(commited)的记录,可能读到最后被回滚的记录,该记录是一个phantom 在一些查询中,使用此隔离级别,可提高效率。因为不受其他进程锁表,锁记录的影响。 

<
> committed read
读到的数据均为提交后的数据。两个进程可同时update 同一条记录。(缺省的隔离级别)
<
> cursor stability 
当隔离级别设置为cursor stability 时,在某一游标内,当前记录不能被其他
的进程update,delete ,但游标内其他的记录可被其他进程update ,delete 
<> repeatable read 
当隔离级别设置为repeatable read 时,在某一游标内有两种情况
1
 该游标的where 子句有索引,则满足条件的所有记录均不能被其他进程 
update ,delete 
(该索引的搜索树的所有节点)
2
 该游标的where 子句不在索引上,则该表的所有记录均不能被其他进程 update,delete 
所以,当使用repeatable read 时,最好有索引,否则相当于锁表,极大损害系统效率。 
3.9. 
使用优化器(update statistics
对表,存储过程的优化的语法如下: 
update statistics [low ] for procedure .. 
[ medium] for table tablename [colname] resolution percent . conf 
[high ]
优化使系统表的信息与实际一致,使搜索树的路径最优。 
同时,整理索引树。
例: 
1. update statistics for table 
2. update statistics for procedure 
3. update statistics for table rta1(bm_cert)
4. update statistics high for table rta1(bm_cert) resolution 0.5
5. update statistics medium for table rta1 resolution 0.5 0.89 
3.10. 
使用复合索引 
建复合索引的原则:
1. 
查询语句中不定的字段尽量放在复合索引的后面。 
有查询语句select * from person where name=” ” sex=”0” and birthday >”1982/12/1” 
则索引建成如下形式效率最好。
Create index idx_person on person(name, ,birthday ,sex) 
而不要建成 
Create index idx_person on person(birthday,sex,name) 
2. 
取值范围大,可能值多的尽量放在复合索引的前面。 
性别只有两种取值“”“ ,最好放在最后。 
姓名可能值最多,最好放在最前,则索引为:
Create index idx_person on person(name,birthday,sex) 
若与第一条有冲突,第一条优先。 
3
 有单独作为条件的,最好放在前面。
如果如下的sql 语句出现的频率较高 
select * from person where name >” “ 
select * from person where name matches “ “ 
name 字段最好放在索引的前面。 
复合索引的建立必须根据整个系统的sql 语句,均衡的考虑。
4. INformIX 
数据库数据复制(CDR 
4.1. 
基本概念 
4.1.1. 
数据复制类型:同步、异步
l  
同步:源数据更新同时马上更新目标数据,系统使用步提交技术保证了数据的完整性。 
步提交要求目标主机和网络环境有较高的可靠性。即任何时候都是可用的。 
l  
异步:目标数据的复制可以根据应用要求设定,但最终要同步所有的数据。在一般的开放系统中,异步方式更为常用,因为它忽略了主机和网络的性能,这往往是一些系统的致命问题。
异步复制又分为如下几种模式:
1) 
主从模式:所有数据更新都是从原到目标,是单向数据复制。如图示:
2) 
工作流模式:数据在服务器间一一流转,也是单向数据复制。如图示:
3) 
任意更新模式:所有定义的数据库之间都互相具有读写权限,它的弊端是容易引起复制冲突,当然CDR 也提供了冲突解决规则。如图示:
4.1.2. 
复制机制:基于触发器和基于日志 s5NT3uZ
l  
触发器方式:这种将与系统竞争对数据库表读写的资源,对正常业务效率有较大影响。并且需要通过应用保证数据完整性。该种方式不可取。
l  
日志方式:由于是采取捕获事物信息的方式,因此不会与系统竞争对数据库表读写资源,效率高。且由系统保持数据一致性、完整性。并有可集中管理的优势。 
4.1.3. CDR 的局限性
l  
仅提供IDS 之间的复制 
l  
不能与HDR 并行使用。 
l  
复制的表不能用view 
l  
一个数据库服务器只能参与一个复制服务
一旦建立了复制服务器:
l  
不能用drop tablerename talbe alter fragment SQL 
l  
复制的表必须有primary key,且不能修改 
l  
不能对字段增删改 
l  
不能建立聚合索引 
4.1.4.
CDR 如何实现 
复制过程主要包括个部分: 
1
 捕获事物 
CDR 
使用基于日志的事物捕获机制获得事物信息。这种方式不会与正常事物竞争对表的存取,所以能获得较好的性能。CDR log 后加上标志,并将它传送到下一步,复制评估。
2
 复制评估 
CDR 
要确定每一条记录的最后值及更新发生时间,以便决定是否进行复制。评估是并行处理的以保证较高性能。评估后CDR 将数据置于消息队列。 
3
 数据分发
消息队列存取方式可以保证所有数据都可以准确到达目标SERVER,它可以忽略主机或网络的状态。当网络发生故障数据存放在本地发送消息队列中,当网络恢复后消息队列再自动将数据分发。 
4 数据同步 :
CDR 
用同步处理保证数据能正确的复制到目标SERVER,当复制数据正确存储到目标SERVER 后,目标SERVER 向源SERVER 发送确认信息。
l  CDR 
的几个组成部分:
1
 复制SERVER:由一个dbserver 组成,与成员SERVER 可以在不同主机或同一主机上。 
2
 复制对象:包括database table columns 还有一些option 如冲突解决规则和范围。 
3
 成员:目标dbserver database table columns  限制条件:必须有primary key 只能复制单表;不能使用Join subquery.
4
 全局目录:是管理复制功能的一系列table , 全局目录在每个dbserver 都有一份,可集中管理。 
l  复制规划 
1
 确定系统拓扑结构,并制作如.复制实例中的表3-1,拓扑如图示:采用树型主从模式。 
2
 有关逻辑日志:逻辑日志的大小应至少容纳一次复制所复制的数据。
3
 有关消息队列:消息队列是一个dbspace,它的大小不仅与逻辑日志有关,而且与网
络中断期间所需缓冲的数据多少有关。(Onconfig 中定义)
4
 影子表:如果定义了冲突解决规则,就要定义影子表,其大小根据规则不同而不同,
如基于时间戳的冲突解决规则需要是复制表的倍。 
5
 假脱机目录:可以指定事物中断后数据暂存目录(缺省:/tmp)。
6
 复制线程个数:是个均衡值即要保证性能也不能浪费(onconfig 中定义)。 
7 网络带宽: 
流量计算如公式:(#transactions per hour)*(#bytes)*(#sites)*130% 
8
 应用分析:估算每天大约有多少数据增删改,分析传送时间安排。
9
.确定要复制的database 用的是unbuffer 方式的逻辑日志。
4.2. CDR 
配置实例
4.2.1. 
系统环境准备 
1
.数据复制源主机:IBM 370 SCO 5.0.5 IDS 7.31.UC2 CBPS 7 
2
.数据复制目的主机:IBM 250 SCO 5.0.5 IDS 7.31.UC2 
3
.检查逻辑日志(logical log)的大小 
4
.建立发送、接受队列dbspace 
5
.确定参与复制的Informix Serverdatabase table 
cdr 
工作表:
Host name Informixserver group database table 
Picc21 ld370222_tcp Grp_picc21 Picc2 * 
Ibm500 ld370220_tcp Grp_ibm500 Picc2 * 
省公司dbserver
地市1 dbserver 地市2 dbserver 地市3 dbserver 
4.2.2. 
确定复制环境 
1. 
复制模式:单向数据复制
2. 
复制时间间隔:立即更新 
4.2.3. 
建立picc21 ibm500 的数据库之间的互访
1) 
分别在picc21 scosysv 上编辑$INformIXDIR/etc/sqlhosts 文件如下: 
grp_picc21 group - - i=1
ld370222_shm onipcshm picc21 ls370222_shm g=grp_picc21 
ld370222_tcp ontlitcp picc21 ls370222_tcp g=grp_picc21 
grp_ibm500 group - - i=2 
ld370220_shm onipcshm ibm500 ls370220_shm g=grp_ibm500 
ld370220_tcp ontlitcp ibm500 ls370220_tcp g=grp_ibm500
2) 
分别在picc21 ibm500 上的/etc/hosts 文件包括如下项: 
176.176.21.78 picc21 picc21 
176.176.66.103 ibm500 
3) 
分别在picc21 ibm500 上的/etc/services 文件包括如下
ls370222_tcp 5889/tcp 
ls370220_tcp 3720/tcp 
4) 
picc21 上的/etc/hosts.equiv 文件包括如下
ibm500 
5) 
ibm500 上的/etc/hosts.equiv 文件包括如下
picc21
以上各步完成picc21 ibm500 的数据库互访,可以通过dbaccess-connect 验证。 
4.2.4. 
定义replicate server 
执行上$INformIXDIR/cdr/crtser.sh 
脚本内容如下:
cdr define server -s sendq -r recvq -A /tmp/ats -R /tmp/ris -I grp_picc21 
注:确保picc21 上的dbspaces sendq recvq 已建立
确保picc21 上的/tmp/ats /tmp/ris 目录已建立 
4.2.5. 
确定复制服务器已建立 
执行picc21 上执行cdr list server
系统显示如下说明replicate server 已建立:
SERVER ID STATE STATUS CONNECTION CHANGED 

grp_picc21 1 Active Local 
1 replicate server 建立时会在picc21 上建立一个名为syscdr database 用来 
管理所有的repliate 信息,因此也可以通过用dbaccess 命令看是否建立了
syscdr 
来确定replicate server 是否正确定义。
2 replicate 必须用DBSERVER GROUP 代替DBSERVER  DBSERVER GROUP  
sqlhosts 
中定义)

阅读(1917) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~