Recent Posts

RSS Feeds

DBA日记 第三部 像Oracle一样思考 3月26日 简单任务 (3)令人惊讶的结果

可以到Oracle粉丝网阅读本节:http://www.oraclefans.cn/forum/showtopic.jsp?rootid=18190

    最近系统的业务量不大,所以客户也同意我们白天就做测试。为了防止误操作,客户把SCOTT账号提供给我做测试。今天我准备做几个测试:

    • l         SEQUENCE缓冲区测试
    • l         表的FREELISTSINITRANS参数调整的测试
    • l         HASH分区测试
    • l         提交批量测试:测试批量大小对插入性能的影响,分别测试批量为800150030005000条记录的响应时间
    • 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参数,性能提升幅度不大。目前sequencecache已经达到了1000,再加大cache,对性能影响不大。看样子sequencecache是不需要再加大了。

第一项测试虽然也在预料之中,不过测试结果还是让我感到有点失望。哪怕能提升23%也是好的啊,看样子只能寄希望于后面的测试项目了。第二项测试的是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组,我并没有将5RAID组全部使用,因为另外一个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



发表一条评论:
  • HTML语法: 启用