DBA日记 第三部 像Oracle一样思考 3月26日 简单任务 (3)令人惊讶的结果
可以到Oracle粉丝网阅读本节:http://www.oraclefans.cn/forum/showtopic.jsp?rootid=18190
最近系统的业务量不大,所以客户也同意我们白天就做测试。为了防止误操作,客户把SCOTT账号提供给我做测试。今天我准备做几个测试:
-
l SEQUENCE缓冲区测试
-
l 表的FREELISTS和INITRANS参数调整的测试
-
l HASH分区测试
-
l 提交批量测试:测试批量大小对插入性能的影响,分别测试批量为800、1500、3000、5000条记录的响应时间
-
l BULK INSERT操作测试
做这种单条SQL执行时间很短的测试,最好的办法是使用profiler工具,将要测试的内容写在一个存储过程里,通过profiler工具来计算平均执行一次所消耗的时间。我首先为每个测试项目都谢了一个小的PL/SQL过程,然后开了7个终端,运行这个存储过程,在第八个终端上的测试过程与其他不同,增加了PROFILER的脚本,这一就能够很方便的采集到每条SQL的执行情况了。
首先测试SEQUENCE,我分别对各种CACHE值进行了测试。首先编写了一个测试用的存储过程:
create or replace procedure testSeq(N integer)
is
i integer;
b integer;
v varchar2(20);
begin
i:=0;
v:=to_char(sysdate,'yyyy-mm-dd:hh24:mi:ss');
dbms_output.put_line(v);
loop
exit when i>N;
i:=i+1;
select sm_idseq.nextval into b from dual;
end loop;
v:=to_char(sysdate,'yyyy-mm-dd:hh24:mi:ss');
dbms_output.put_line(v);
end;
/
在第八个终端上,执行下面的脚本:
declare
err number;
begin
err:=DBMS_PROFILER.START_PROFILER (‘test seq 1000’);
testseq(200000);
err:=DBMS_PROFILER.STOP_PROFILER ;
end;
/
脚本执行结束后,可以通过下列脚本查看存储过程中每一行执行的情况:
column RUN_COMMENT format a40 truncate;
select runid, run_date, RUN_COMMENT from plsql_profiler_runs order by runid;
column unit_name format a15 truncate;
column occured format 999999 ;
column line# format 99999 ;
column tot_time format 999999.999999 ;
select p.unit_name, p.occured, p.tot_time, p.line# line,
substr(s.text, 1,75) text
from
(select u.unit_name, d.TOTAL_OCCUR occured,
(d.TOTAL_TIME/1000000000) tot_time, d.line#
from plsql_profiler_units u, plsql_profiler_data d
where d.RUNID=u.runid and d.UNIT_NUMBER = u.unit_number
and d.TOTAL_OCCUR >0
and u.runid= &RUN_ID) p,
user_source s
where p.unit_name = s.name(+) and p.line# = s.line (+)
order by p.unit_name, p.line#;
其中的参数,run_id来自于plsql_profiler_units,可以通过我们执行PROFILER的时候使用的名称来查找刚才的测试对应的run_id,一般来说还有个更简单的查找方法,就是找最后一个run_id,因为run_id是通过sequence产生的,我们刚刚做过的测试肯定是最后一个。
上面的查询的结果如下:
UNIT_NAME OCCURED TOT_TIME LINE TEXT
--------------- ------- -------------- ----------
<anonymous> 1 .000781 4
<anonymous> 1 .009996 5
<anonymous> 1 .002121 6
TESTLOG 1 .001145 6 i:=0;
TESTLOG 50001 40.602085 8 exit when i>=N;
TESTLOG 50000 59.097742 9 i:=i+1;
TESTLOG 50000 2948.819922 10 select sm_idseq.nextval into v from dual;
PROFILER可以计算出每一行执行的次数,以及总共消耗的时间。从而可以为我们提供准确的测试数据。SEQUENCE的测试结果如下:
|
CACHE |
并发数量 |
执行次数 |
测试时间(毫秒) |
平均每次执行时间 |
|
2 |
8 |
200001 |
942122 |
4.7 |
|
100 |
8 |
200001 |
73282 |
0.366 |
|
1000 |
8 |
200001 |
48250 |
0.241 |
|
5000 |
8 |
200001 |
47129 |
0.236 |
|
20000 |
8 |
200001 |
43299 |
0.216 |
从测试结果来看,sequence缓冲区的增加可以提高sequence的访问性能,不过超过1000后,加大cache参数,性能提升幅度不大。目前sequence的cache已经达到了1000,再加大cache,对性能影响不大。看样子sequence的cache是不需要再加大了。
第一项测试虽然也在预料之中,不过测试结果还是让我感到有点失望。哪怕能提升2、3%也是好的啊,看样子只能寄希望于后面的测试项目了。第二项测试的是sm_histable表的核心参数,测试比对的是完全按照目前的参数创建的一张测试表,和修改了freelists,initrans,initial,next这几个参数的测试表。表的分区方式,以及存储的表空间等属性都没有修改,索引也完全按照生产环境创建。这次测试的结果让人感到十分惊诧:
|
项目 |
相关业务 |
调整前(秒) |
调整后(秒) |
对比说明 |
|
整体时间 |
短信历史记录应用: DB_DaeMon程序 |
128.67 |
112.35 |
速度提升:14.53% |
|
平均每条记录的插入时间 |
|
0.002573 |
0.002247 |
速度提升:14.53% |
调整这几个参数后,并发插入的性能居然提升了14.5%,这有点出乎我的预料。基本上达到了我预期的最高值。兴奋之余,我马上进行了HASH分区的测试,我修改了这张表的定义,将表分区从10个修改为8个,分别存储在4个表空间上,这4个表空间分别属于不同的RAID组,我并没有将5个RAID组全部使用,因为另外一个RAID组上,存放了REDO LOG文件,这么设计是为了达到REDO LOG和数据文件互相不干扰的目的。
PARTITION BY HASH (ID_HINT)
PARTITIONS 8
STORE IN (CQYDSMSC_CENTER1,CQYDSMSC_CENTER2,CQYDSMSC_CENTER3,CQYDSMSC_CENTER4)
测试的结果如下:
|
项目 |
相关业务 |
调整前(秒) |
调整后(秒) |
对比说明 |
|
整体时间 |
短信历史记录应用: DB_DaeMon程序 |
90.397 |
78.793 |
在存储参数提升14.53%的基础上,再提升14.73% |
|
Permalink
No Comments
发表一条评论:
|