学历代表过去、能力代表现在、学习力代表未来

发布新日志

  • Jprofiler远程监控resin4.0

    2012-05-15 17:16:53

    1.到官网下载linux安装包,如:jprofiler_linux_6_2_4.rpm
    2.上传该安装包到linxu服务器上/opt目录下,重命名: mv jprofiler_linux_6_2_4.rpm jprofiler6.rmp
      (重命名步骤为可选操作,是为了安装时能生成简单的文件目录 jprofiler6)
    3.安装: rpm -ivh jprofiler_linux_6_2_4.rpm
    4.安装完毕后,在etc/profile中添加:
      #Jprofiler Conf
      JPROFILER_HOME=/opt/jprofiler6/bin/linux-x64
      export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JPROFILER_HOME
    5.resin设置:进入/conf/resin.xml中,添加如下信息:
      在<class-loader>..</class-loader>中加入
         <tree-loader path="/usr/local/jprofiler6/lib" />
         <tree-loader path="/usr/local/jprofiler6/bin" />
      在<server-default>...</server-default>中加入
         <jvm-arg>-agentpath:/opt/jprofiler6/bin/linux-x64/libjprofilerti.so=port=8849,nowait</jvm-arg>
    6.重启resin,在resin日志中可以看到:
      JProfiler> Protocol version 32
      JProfiler> Using JVMTI
      JProfiler> JVMTI version 1.1 detected.
      JProfiler> 64-bit library
      JProfiler> Don't wait for frontend to connect.
      JProfiler> Starting up without initial configuration.
      JProfiler> Listening on port: 8849.
      JProfiler> Instrumenting native methods.
      JProfiler> Can retransform. classes.
      JProfiler> Can retransform. any class.
      JProfiler> Native library initialized
      JProfiler> VM initialized
      JProfiler> Hotspot compiler enabled
      ...
    7.在本地PC上安装对应版本的Jprofiler客户端,设置连接即可
    备注:resin4.x和resin3.x以前的版本相比,resin4.x没有resin.conf文件,可直接在resin.xml中配置
          步骤6中:如果resin.xml文件中没有<class-loader>..</class-loader>和<server-default>...</server-default>,可在<cluster>...</cluster>中手动添加
        
     
  • loadrunner 在HTTP接口测试中的应用

    2012-05-14 23:30:12

    来源:http://www.51testing.com/?uid-23978-action-viewspace-itemid-132923

     

    对一个手机音乐播放器项目进行测试,需要测试和服务器交互的信令,分析了信令协议后,还是确定使用LR来执行

    该播放器和服务器的交互采用HTTP协议,支持POST和GET两种方式,使用Loadrunner的web_custom_request可以很轻松实现该功能

    脚本如下:

    Action()
    {
    //4.2.2 歌曲详细信息访问接口POST方式实现
     web_custom_request("music1",
      "URL=http://172.16.11.162:9055/musicSync/syncMusicDetail.do",
      "Method=POST",
      "Resource=0",
      "Referer=",
      "Mode=HTTP",
      "EncType=text/html; charset=UTF-8",
      "Body=<?xml version=/"1.0/" encoding=/"UTF-8/"?>/r/n"
      "<message>/r/n"
      "<spcode>16</spcode>/r/n"
      "<hsman>aux</hsman >/r/n"
      "<hstype>1111</hstype>/r/n"
      "<imsi>232323</imsi>/r/n"
      "<musicid>119</musicid >/r/n"
      "</message>",
      LAST);

    //4.2.2 歌曲详细信息访问接口GET方式实现
      web_custom_request("music2",
      "URL=http://172.16.11.162:9055/musicSync/syncMusicDetail.do?sp=16&hm=aux&ht=1111&is=232323&id=119",
      "Method=GET",
      "Resource=0",
      "Referer=",
      "Mode=HTTP",
      "EncType=text/html; charset=UTF-8",
      "Body=",
      LAST);

     return 0;
    }

    两种方式实现的功能是相同的,而要观察服务器的返回信息,LR的HTTP协议方式执行时只需要在日志选项中选中扩展日志中的“服务端返回的数据”即可,返回结果如下:

    虚拟用户脚本已启动
    正在开始操作 vuser_init。
    Web Turbo 重播 LoadRunner 8.1.0 for WINXP; Web 内部版本 4788   [MsgId: MMSG-27143]
    运行时设置文件: "F:/music/12530L//default.cfg"   [MsgId: MMSG-27141]
    正在结束操作 vuser_init。
    正在运行 Vuser...
    正在开始迭代 1。
    正在开始操作 Action。
    Action.c(4): “http://172.16.11.162:9055/musicSync/syncMusicDetail.do”(RelFrameId=1)的 t=1833ms: 111 个字节响应标头
    Action.c(4):     HTTP/1.1 200 OK/r/n
    Action.c(4):     Server: Apache-Coyote/1.1/r/n
    Action.c(4):     Transfer-Encoding: chunked/r/n
    Action.c(4):     Date: Wed, 24 Jun 2009 06:43:13 GMT/r/n
    Action.c(4):     /r/n
    Action.c(4): “http://172.16.11.162:9055/musicSync/syncMusicDetail.do”(RelFrameId=1)的 t=1945ms: 3 个字节成块响应开销
    Action.c(4):     3/r/n
    Action.c(4): “http://172.16.11.162:9055/musicSync/syncMusicDetail.do”(RelFrameId=1)的 t=1956ms: 3 个字节成块响应正文
    Action.c(4):     200
    Action.c(4): “http://172.16.11.162:9055/musicSync/syncMusicDetail.do”(RelFrameId=1)的 t=1966ms: 2 个字节成块响应开销
    Action.c(4):     /r/n
    Action.c(4): “http://172.16.11.162:9055/musicSync/syncMusicDetail.do”(RelFrameId=1)的 t=1977ms: 5 个字节成块响应开销
    Action.c(4):     0/r/n
    Action.c(4):     /r/n
    Action.c(4): web_custom_request("music1") 已成功,3 个正文字节,111 个标头字节,10 个成块开销字节   [MsgId: MMSG-26385]
    正在结束操作 Action。
    正在结束迭代 1。
    正在结束 Vuser...
    正在开始操作 vuser_end。
    正在结束操作 vuser_end。
    Vuser 已终止。

    响应正文中返回200代表请求成功,再配合对服务端数据库的数据检查即完美地实现了对该HTTP协议交互项目的测试.

  • LR 接口测试(Windows socket方式)

    2012-04-28 09:40:49

    1.在 data.ws 中定义发送报文(报文内容、报文长度)、接收报文长度
      ;WSRData 2 1

      //发送报文
      send  buf1 100
       "00479000<psam>;422006402831111151043130290701;<telno>0000"
      //接收报文
      recv buf2 100
     
      -1
     
    2.创建socket连接,并发送、接收报文
      lrs_startup(257);
      //设置socket连接创建超时时间
      lrs_set_accept_timeout(20,20000);
      //创建一条PC和接口服务的socket连接
      lrs_create_socket("socket0", "TCP", "LocalHost=12405", "Backlog=5",  LrsLastArg);
      lrs_accept_connection("socket0", "socket1");

      lrs_send("socket1", "buf1", LrsLastArg);
      lrs_receive("socket1", "buf2", LrsLastArg);
     
    3.接口测试中常用的函数
      char *recvbuf1;
      int recvlen1=0;
     
      lrs_create_socket("socket0", "TCP", "LocalHost=12405", "Backlog=5",  LrsLastArg);
      lrs_accept_connection("socket0", "socket1");

      lrs_send("socket1", "buf1", LrsLastArg);
      lrs_receive("socket1", "buf2", LrsLastArg);
     
      lrs_get_last_received_buffer("socket1",&recvbuf1,&recvlen1);
     
      if (recvlen1 == 100)
      {
         lr_output_message("正确接收报文");
      }
     
  • LR9.5卸载安装

    2012-04-23 15:24:33

    第一步:用LR8.0中的mlr5lprg.dll、lm70.dll覆盖LR9.1(9.5)安装目录下“bin”文件夹中的对应文件;
    第二步:手动修改注册表,删除下面内容
    [HKEY_LOCAL_MACHINE\SOFTWARE\Mercury Interactive\LoadRunner\License2]
    [HKEY_LOCAL_MACHINE\SOFTWARE\Mercury Interactive\LoadRunner\License2\History]
    "AIBGEBFW-JVED-ZKEKEKEKEKEBDNQAF-KBRDN"=""
    [HKEY_LOCAL_MACHINE\SOFTWARE\Mercury Interactive\LoadRunner\License2\PermanentLicense]
    @="AIBGEBFW-JVED-ZKEKEKEKEKEBDNQAF-KBRDN"
    "last"="AIBGEBFW-JVED-ZKEKEKEKEKEBDNQAF-KBRDN"
    [HKEY_LOCAL_MACHINE\SOFTWARE\Mercury Interactive\LoadRunner\License2\TemporaryLicense]@="AEBGEBFS-AKEKEKEKE-KAUCA"
    [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{87B3ADD4-21EB-11d5-93EF-00105AA0FD2D}]
    @="IControl"
    第三步:添加下面的licence,即可使用。
     
    global-100: AEAMAUIK-YAFEKEKJJKEEA-BCJGI
    web-10000: AEABEXFR-YTIEKEKJJMFKEKEKWBRAUNQJU-KBYGB
    6.5w license:AEACFSJI-YJKJKJJKEJIJD-BCLBR
  • Jprofiler服务端在Linux上的安装注意事项--tomcat

    2012-04-17 08:46:36

    注意:安装前先用rpm -q jprofiler查询linux上是否已安装jprofiler
     
    1.到官网下载linux安装包,如:jprofiler_linux_7_1_1.rpm
    2.上传该安装包到linxu服务器上/opt目录下,重命名: mv jprofiler_linux_7_1_1.rpm jprofiler7.rmp
      (重命名步骤为可选操作,是为了安装时能生成简单的文件目录 jprofiler7)
    3.安装: rpm -ivh jprofiler_linux_7_1_1.rpm
    4.安装完毕后,在etc/profile中添加:
      #Jprofiler Conf
      JPROFILER_HOME=/opt/jprofiler7/bin/linux-x64
      export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JPROFILER_HOME
    5.以tomcat服务为例,在catalina.sh中添加:
      #Jprofiler Conf
      JAVA_OPTS="$JAVA_OPTS -agentlib:jprofilerti=port=8849-Xbootclasspath/a:/opt/jprofiler7/bin/agent.jar"
    6.在startup.sh中添加:
      #Jprofiler Conf
      CATALINA_OPTS="-agentpath:/opt/jprofiler7/bin/linux-x64/libjprofilerti.so=port=8849,nowait$CATALINA_OPTS"
    export CATALINA_OPTS
  • 网络流量监控工具

    2012-02-07 15:44:23

    NetMeter

      一个不错且免费的网络联机速度监测软件,它可以监测你目前的网络联机速度,包含上传及下载的实时速度,并以漂亮的长条图表显示出来。Net Meter 用图形和数字化方式显示本地网络流量的详细信息。它同时监视一个或者多个LAN和WAN网络流量,从下载,上传,最大速率等所有网络流量它都用日志功能记录下来,方便用户以后查询统计。Net Meter 在各种网络连接下可工作,包括 ADSL、modem、LAN 等。Net Meter 最大特色算是它能实时图形化和数字化网络流量细节,让用户能清楚明白了解网络状况,防止我们优秀的网络被一些下载软件“占用了”。图形及文字的颜色,字体可以在选项界面自由设置。你还可以设置监控一个声音,当流量或速率超过某个值的时候通知你。
     

    NetPeeker

      NetPeeker是一个网络监视软件 ,能够实时显示每个应用程序或进程占用网络的情况(如使用流量等情况)。并可以记录网络传输,安全事件和网络传输状态报告,并显示每个应用程序的周期网路使用情况和远程IP地址,捕获网络传输,查询域名(WHOIS),能监视支持ICS(Internet connection Sharing)的远程计算机.支持NETBIOS文件传输,还能监视本地文件拷贝速度.
      这款软件是专门针对某些P2P软件偷偷上传造成的网络拥堵,网站访问缓慢的情况而设计的,使用该软件可以对每个应用程序的网络上传进行控制,让上网重新流畅起来.
     

    NetLimiter

      NetLimiter是一款运行在Windows 98/98SE/me/2000/xp/2003上的网络流量控制软件。通过它,您可以直接来控制每个程序对Internet的访问以及流量分配情况。例如,您可以用NetLimiter来为单个程序甚至是单个网络连接限定其上载和下载速度。通过非常简单的设置,NetLimiter就可以让你随心所欲地在各个程序之间分配网络带宽。

    iperf

    Iperf 是一个网络性能测试工具。Iperf可以测试最大TCP和UDP带宽性能。Iperf具有多种参数和UDP特性,可以根据需要调整。Iperf可以报告带宽,延迟抖动和数据包丢失。

      iperf 分为两种版本,unix/linux版和windows版,unix/linux版更新比较快,版本最新。windows版更新慢。windows版的iperf叫jperf,或者xjperf。jperf是在iperf基础上开发了更好的UI和新的功能。

    ixchariot

      美国IXIA公司的应用层性能测试软件IxChariot是一个独特的测试工具,也是在应用层性能测试领域得到业界认可的测试系统。对于企业网而言,IxChariot可应用于设备选型、网络建设及验收、日常维护等3个阶段,提供设备网络性能评估、故障定位和SLA基准等服务。
      IxChariot由两部分组成:控制端(Console)和远端(Endpoint),两者都可安装在普通PC或者服务器上,控制端安装在Windows操作系统上,远端支持各种主流的操作系统。
     

    SmartBit

    SmartBits是数据通信业界广泛认同的对于网络设备及网络性能测试的标准测量仪表。使用SmartBits可以帮助用户测试:交换机、路由器的性能,如吞吐量、延迟、丢包等指标,更可以在一个端口中模拟上千万个网络的数量,并可以对其各自的性能进行分析,测试出不同的QoS下不同流量的表现。除了对交换机和路由器的基本网络设备的测试, SmartBits还能够应用在网络安全设备、接入网设备、通信终端、ATM设备进行测试和分析。SmartBits目前提供了业界最全面的网络接口类型。

  • 【转载】Oracle SQL性能优化技巧大总结

    2011-12-20 11:09:02

    (1)选择最有效率的表名顺序(只在基于规则的优化器中有效): 
        ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表. oracle首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并
      (2) WHERE子句中的连接顺序.: 
        ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾. 
      (3) SELECT子句中避免使用 ‘ * ‘: 
        ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间 
      (4) 减少访问数据库的次数: 
        ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等; 
      (5) 在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200 (ARRAY[SIZE] {20(默认值)|n} 置一批的行数,是SQL*PLUS一次从数据库获取的行数,有效值为1至5000. 大的值可提高查询和子查询的有效性,可获取许多行,但也需要更多的内存.当超过1000时,其效果不大)
      (6) 使用DECODE函数来减少处理时间: 
        使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表. (DECODE函数的作用:它可以将输入数值与函数中的参数列表相比较,根据输入值返回一个对应值。函数的参数列表是由若干数值及其对应结果值组成的若干序偶形式。当然,如果未能与任何一个实参序偶匹配成功,则函数也有默认的返回值。
        select decode( x , 1 , ‘x is 1 ’, 2 , ‘x is 2 ’, ‘others’) from dual
      当x等于1时,则返回‘x is 1’。
      当x等于2时,则返回‘x is 2’。
      否则,返回others)
      (7) 整合简单,无关联的数据库访问: 
        如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系) 
      (8) 删除重复记录: 
        最高效的删除重复记录方法 ( 因为使用了ROWID)例子: 
    DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) 
    FROM EMP X WHERE X.EMP_NO = E.EMP_NO); 
      (9) 用TRUNCATE替代DELETE: 
        当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况) 而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短. (译者按: TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML) 
      (10) 尽量多使用COMMIT: 
        只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少: 
    COMMIT所释放的资源: 
    a. 回滚段上用于恢复数据的信息. 
    b. 被程序语句获得的锁 
    c. redo log buffer 中的空间 
    d. ORACLE为管理上述3种资源中的内部花费 
    (11) 用Where子句替换HAVING子句: 
        避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销. (非oracle中)on、where、having这三个都可以加条件的子句中,on是最先执行,where次之,having最后,因为on是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的,where也应该比having快点的,因为它过滤数据后才进行sum,在两个表联接时才用on的,所以在一个表的时候,就剩下where跟having比较了。在这单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是where可以使用rushmore技术,而having就不能,在速度上后者要慢如果要涉及到计算的字段,就表示在没计算之前,这个字段的值是不确定的,根据上面写的工作流程,where的作用时间是在计算之前就完成的,而having就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。在多表联接查询时,on比where更早起作用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由where进行过滤,然后再计算,计算完后再由having进行过滤。由此可见,要想过滤条件起到正确的作用,首先要明白这个条件应该在什么时候起作用,然后再决定放在那里 
      (12) 减少对表的查询: 
        在含有子查询的SQL语句中,要特别注意减少对表的查询.例子: 
    SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT 
    TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604) 
      (13) 通过内部函数提高SQL效率.: 
        复杂的SQL往往牺牲了执行效率. 能够掌握上面的运用函数解决问题的方法在实际工作中是非常有意义的 
      (14) 使用表的别名(Alias): 
        当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误. 
      (15) 用EXISTS替代IN、用NOT EXISTS替代NOT IN: 
        在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率. 在子查询中,NOT IN子句将执行一个内部的排序和合并. 无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS. 
    例子: 
    (高效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB') 
    (低效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB') 
      (16) 识别'低效执行'的SQL语句: 
        虽然目前各种关于SQL优化的图形化工具层出不穷,但是写出自己的SQL工具来解决问题始终是一个最好的方法: 
    SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run, 
    SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS>0 AND BUFFER_GETS > 0 AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8 ORDER BY 4 DESC; 
      (17) 用索引提高效率: 
        索引是表的一个概念部分,用来提高检索数据的效率,ORACLE使用了一个复杂的自平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快. 当ORACLE找出执行查询和Update语句的最佳路径时, ORACLE优化器将使用索引. 同样在联结多个表时使用索引也可以提高效率. 另一个使用索引的好处是,它提供了主键(primary key)的唯一性验证.。那些LONG或LONG RAW数据类型, 你可以索引几乎所有的列. 通常, 在大型表中使用索引特别有效. 当然,你也会发现, 在扫描小表时,使用索引同样能提高效率. 虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价. 索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改. 这意味着每条记录的INSERT , DELETE , UPDATE将为此多付出4 , 5 次的磁盘I/O . 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.。定期的重构索引是有必要的.: 
    ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME> 
      (18) 用EXISTS替换DISTINCT: 
        当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换, EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果. 例子: 
    (低效): SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E 
    WHERE D.DEPT_NO = E.DEPT_NO (高效): SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO); 
      (19) sql语句用大写的;因为oracle总是先解析sql语句,把小写的字母转换成大写的再执行 
      (20) 在java代码中尽量少用连接符“+”连接字符串!
    (21) 避免在索引列上使用NOT 通常,  
        我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响. 当ORACLE”遇到”NOT,他就会停止使用索引转而执行全表扫描. 
      (22) 避免在索引列上使用计算. 
        WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描. 举例: 低效:
    SELECT … FROM DEPT WHERE SAL * 12 > 25000; 高效:
    SELECT … FROM DEPT WHERE SAL > 25000/12;
      (23) 用>=替代> 
        高效: 
    SELECT * FROM EMP WHERE DEPTNO >=4 低效: 
    SELECT * FROM EMP WHERE DEPTNO >3 两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录.

      (24) 用UNION替换OR (适用于索引列) 
        通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低. 在下面的例子中, LOC_ID 和REGION上都建有索引. 高效: SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 UNION SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE REGION = “MELBOURNE” 低效: SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 OR REGION = “MELBOURNE” 如果你坚持要用OR, 那就需要返回记录最少的索引列写在最前面. 
      (25) 用IN来替换OR 
        这是一条简单易记的规则,但是实际的执行效果还须检验,在ORACLE8i下,两者的执行路径似乎是相同的.  
    低效: SELECT…. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30 高效 SELECT… FROM LOCATION WHERE LOC_IN IN (10,20,30); 
      (26) 避免在索引列上使用IS NULL和IS NOT NULL 
        避免在索引中使用任何可以为空的列,ORACLE将无法使用该索引.对于单列索引,如果列包含空值,索引中将不存在此记录. 对于复合索引,如果每个列都为空,索引中同样不存在此记录. 如果至少有一个列不为空,则记录存在于索引中.举例: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) , ORACLE将不接受下一条具有相同A,B值(123,null)的记录(插入). 然而如果所有的索引列都为空,ORACLE将认为整个键值为空,而空不等于空. 因此你可以插入1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引. 
    低效: (索引失效) SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL; 高效: (索引有效) SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0; 
      (27) 总是使用索引的第一个列: 
        如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引. 这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引
      (28) 用UNION-ALL 替换UNION ( 如果有可能的话): 
        当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序. 如果用UNION ALL替代UNION, 这样排序就不是必要了. 效率就会因此得到提高. 需要注意的是,UNION ALL 将重复输出两个结果集合中相同记录. 因此各位还是要从业务需求分析使用UNION ALL的可行性. UNION 将对结果集合排序,这个操作会使用到SORT_AREA_SIZE这块内存. 对于这块内存的优化也是相当重要的. 下面的SQL可以用来查询排序的消耗量 
    低效: 
    SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95' UNION SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95' 高效: SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS
    WHERE TRAN_DATE = '31-DEC-95' UNION ALL SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95'
      (29) 用WHERE替代ORDER BY: 
    ORDER BY 子句只在两种严格的条件下使用索引. 
    ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序. 
    ORDER BY中所有的列必须定义为非空. 
    WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列. 
    例如: 表DEPT包含以下列: 
    DEPT_CODE PK NOT NULL 
    DEPT_DESC NOT NULL 
    DEPT_TYPE NULL 
    低效: (索引不被使用) SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE 高效: (使用索引) SELECT DEPT_CODE FROM DEPT WHERE DEPT_TYPE > 0 
      (30) 避免改变索引列的类型.: 
        当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换. 
    假设 EMPNO是一个数值类型的索引列. SELECT … FROM EMP WHERE EMPNO = ‘123' 实际上,经过ORACLE类型转换, 语句转化为: SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123') 幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变. 现在,假设EMP_TYPE是一个字符类型的索引列. SELECT … FROM EMP WHERE EMP_TYPE = 123 这个语句被ORACLE转换为: SELECT … FROM EMP WHERETO_NUMBER(EMP_TYPE)=123 因为内部发生的类型转换, 这个索引将不会被用到! 为了避免ORACLE对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时, ORACLE会优先转换数值类型到字符类型 
    (31) 需要当心的WHERE子句: 
        某些SELECT 语句中的WHERE子句不使用索引. 这里有一些例子. 在下面的例子里, (1)‘!=' 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中. (2) ‘||'是字符连接函数. 就象其他函数那样, 停用了索引. (3) ‘+'是数学函数. 就象其他数学函数那样, 停用了索引. (4)相同的索引列不能互相比较,这将会启用全表扫描. 
      (32) a. 如果检索数据量超过30%的表中记录数.使用索引将没有显著的效率提高. 
    b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别. 而通常情况下,使用索引比全表扫描要块几倍乃至几千倍! 
      (33) 避免使用耗费资源的操作: 
        带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写. 如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也是可以考虑的, 毕竟它们的可读性很强(Oracle查询运算:intersect和minus intersect运算 返回查询结果中相同的部分 exp:各个部门中有哪些相同的工种 select job from account intersect select job from research intersect select job from sales; minus运算 返回在第一个查询结果中与第二个查询结果不相同的那部分行记录。 有哪些工种在财会部中有,而在销售部中没有)
      (34) 优化GROUP BY: 
        提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉.下面两个查询返回相同结果但第二个明显就快了许多. 
    低效: 
    SELECT JOB , AVG(SAL)
    FROM EMP GROUP JOB HAVING JOB = ‘PRESIDENT' OR JOB = ‘MANAGER' 
    高效:
    SELECT JOB , AVG(SAL)
    FROM EMP
    WHERE JOB = ‘PRESIDENT'
    OR JOB = ‘MANAGER' GROUP JOB

  • 【转载】关于linux中内存、buffer、cache的理解

    2011-11-28 16:33:10

    http://www.quke.org/log-424.html

    在使用了xen以后发现开机后内存直接占了一半,似乎不正常,就查找了些linux内存方面的资料。

    我们一开始,先从Free命令说起。
    free 命令相对于top 提供了更简洁的查看系统内存使用情况:

    1. [/root]free 
    2.              total       used       free     shared    buffers     cached 
    3. Mem:        542668     263680     278988          0      66408      93168 
    4. -/+ buffers/cache:     104104     438564 
    5. Swap:      1048568          0    1048568 
    6. [/root] 
    Mem:表示物理内存统计 
    -/+ buffers/cached:表示物理内存的缓存统计 
    Swap:表示硬盘上交换分区的使用情况,这里我们不去关心。
    系统的总物理内存:542668Kb(512M),但系统当前真正可用的内存并不是第一行free 标记的 278988Kb,它仅代表未被分配的内存。
    我们使用total1、used1、free1、used2、free2 等名称来代表上面统计数据的各值,1、2 分别代表第一行和第二行的数据。
    total1:表示物理内存总量。 
    used1:表示总计分配给缓存(包含buffers 与cache )使用的数量,但其中可能部分缓存并未实际使用。 
    free1:未被分配的内存。 
    shared1:共享内存,一般系统不会用到,这里也不讨论。 
    buffers1:系统分配但未被使用的buffers 数量。 
    cached1:系统分配但未被使用的cache 数量。buffer 与cache 的区别见后面。 
    used2:实际使用的buffers 与cache 总量,也是实际使用的内存总量。 
    free2:未被使用的buffers 与cache 和未被分配的内存之和,这就是系统当前实际可用内存。
    可以整理出如下等式:
    total1 = used1 + free1
    total1 = used2 + free2
    used1 = buffers1 + cached1 + used2
    free2 = buffers1 + cached1 + free1
    buffer 与cache 的区别
    A buffer is something that has yet to be "written" to disk. A cache is something that has been "read" from the disk and stored for later use.
    更详细的解释参考:Difference Between Buffer and Cache
    对于共享内存(Shared memory),主要用于在UNIX 环境下不同进程之间共享数据,是进程间通信的一种方法,一般的应用程序不会申请使用共享内存,笔者也没有去验证共享内存对上面等式的影响。如果你有兴趣,请参考:What is Shared Memory?
    cache 和 buffer的区别
    Cache:高速缓存,是位于CPU与主内存间的一种容量较小但速度很高的存储器。由于CPU的速度远高于主内存,CPU直接从内存中存取数据要等待一定时间周期,Cache中保存着CPU刚用过或循环使用的一部分数据,当CPU再次使用该部分数据时可从Cache中直接调用,这样就减少了CPU的等待时间,提高了系统的效率。Cache又分为一级Cache(L1 Cache)和二级Cache(L2 Cache),L1 Cache集成在CPU内部,L2 Cache早期一般是焊在主板上,现在也都集成在CPU内部,常见的容量有256KB或512KB L2 Cache。
    Buffer:缓冲区,一个用于存储速度不同步的设备或优先级不同的设备之间传输数据的区域。通过缓冲区,可以使进程之间的相互等待变少,从而使从速度慢的设备读入数据时,速度快的设备的操作进程不发生间断。
    Free中的buffer和cache:(它们都是占用内存):
    buffer : 作为buffer cache的内存,是块设备的读写缓冲区
    cache: 作为page cache的内存, 文件系统的cache
    如果 cache 的值很大,说明cache住的文件数很多。如果频繁访问到的文件都能被cache住,那么磁盘的读IO 必会非常小。

    总结如下:

    linux内存分配出去了,但是可能并没实际使用。

  • 【转载】闲话QTP——当孔明遇上QTP时

    2011-11-04 11:13:10

     话说公元250 年2 月30 日,孔明设计并制造出一台集各种武器于一身的超

      级杀人武器霸王——“拿你命300”,它能识别出放入其内的数百种弹药并用相

      应的投弹器发射出去,使用起来非常方便,非常傻瓜。比如放入石头它会用投石

      机投掷,放入箭簇则以弓弩射出。现在需要测试它的功能是否达到这种要求。但

      问题是:

      1、测试过程耗时很长(关系到成本);

      2、测试过程很单调,就是放入弹药(输入),看它会用哪种发射器去发射

      (输出),如此重复相当多次,并且不用查看中间的工作过程,(即黑盒测试,

      根据输入检查输出是否符合要求);

      3、此机批量生产后每台都要做完全相同的测试。

      而孔明日理万机,故无暇顾及此机,如果花点时间培训一个专人来负责,那

      以后就省力又省心,一个人顶过去十个(可重复测试)……然则何人来测?发愁

      之际,吏部调一人前来。此人名叫齐铁炮,英文名是QTP,他不懂汉语,只会

      VBscript,最擅模仿,动作神速,能工作数月而不知疲倦。那不就是传说中的变

      形金刚?不,因为他的缺点是智商为零,非常死板,不知变通。

      根据这些特点,孔明这样安排他工作:

      1、录脚本

      孔明先以石头为例做一遍测试过程,然后QTP 把孔明的动作都逐一记在本

      子上(即脚本),再依照脚本来做就完全重现了孔明的测试过程。

      2、插入检查点

      然后孔明又告诉他如何将预设的期望值与测得的实际值对比来判断功能是

      否正确。比如:(对于放入的石头,按发射按钮后,)如果输出端可见一投石器

      升起并投掷此石,则表示该功能通过。QTP 也把它记下来并也成功照做。

      3、参数化

      “好,灰常好,QTP,现在你改用箭去测试。”

      “可是丞相,我记下的脚本中只有‘……打开弹药舱,放入石头……’,并

      没有关于如何使用‘箭’的内容,你要做一遍给我看或者明确告诉When,Where

      and How 去用它,不然我无从下手。”

      孔明一听吐血,这QTP 还真不愧是笨蛋,要是每种输入的弹药都要做一遍

      那还不如自己测试,于是他决定在QTP 原有的脚本上修改,用参数表记下所有

      需要测试的弹药,在‘放入石头’的‘石头’处改用此参数表,告诉QTP 每次

      到这一步时就取表中的下一种弹药来测,在检查点中也改用对应的期望值参数表

      来判断结果。这下QTP 才能按孔明的意愿顺利测试下去。

          

          其间还涉及一些问题:

      对象库

      孔明发现,QTP 在记录脚本时要用掉很多本子,仔细一看,这些本子叫“对

      象库”,他把有关对象的属性都记录到里面去了。比如某个按钮的属性为:

      类型:按钮,

      名称:发射,

      颜色:红色,

      密度:3000g/m3,

      材料:聚乙烯,

      重量:100g,

      位置:左边顶部

      ……

      为的是在测试时根据这些属性来确定对象,以便操作。可是要确定对象一般

      只需特定的两三个属性就够了(像刚才那个按钮只要用“类型:按钮,名称:发

      射”就足以标识它),其它属性变得多余且占空间。

      “QTP 啊,我不是给你指定了几个属性来标识对象吗?你把全部都记下来

      干嘛?洛阳纸贵啊”

      “丞相,我这样做是有好处的,如果根据指定的属性无法确定对象,我还有

      个特技,我可以用其它属性来进行智能识别。”

      “就你那智商还智能识别……”

      描述性编程

      为了节省资源,孔明令QTP 不要记录对象属性到对象库,改为直接在脚本

      中描述对象,比如对刚才那个按钮,只需描述类型和名称就可以找到它了。

      自动化测试(增强)

      有一次孔明出征去了,不在测试现场,QTP 在一炷香后还确定不了要按哪

      个按钮,就写了一张便条放在孔明办公桌上,其内容是:

      “无法找到“锁定目标”按钮所在的控制面板,应如何处理?你有几个选择:

      A、别测了,先吃饭去B、我不管,反正你不能停C、你来调戏试D、去掉两

      个不推荐的选项E、向现场将士求助。”

      然后暂停测试,干等孔明的指示,直到数月后孔明回来。鉴于此事,孔明令

      QTP 以后一旦遇到无法解决的问题或者完成测试后立刻向他报告,方式可以是

      用发短信、语音通话、发邮件、即时通讯工具、飞鸽传书等。

      需求变更

      后来孔明又对此机增加了一个功能:如果放入玉米、地瓜之类的食物,输出

      来的就是烤熟的了,这样将士们作战时就可以打到哪吃到哪。如果一并测试这个

      功能应该怎么改脚本?很容易想到:在“放入石头”的参数表中增加食物,在后

      面检查点中增加相应期望结果即可。改好脚本后QTP 照做,可这一次测试结果

      却是投石器把玉米抛了过去,给敌人送去了粮食,bug,终于出现了……

  • QTP使用过程中的问题及解决

    2011-10-10 11:01:56

    3.问题:无法正常登录QTP自带的订票网站

    解决方法:查看PC是否按照Java(TM) SE软件(关键);重新注册账号(数字优先)

     

    2.问题:QTP无法识别鼠标双击操作

    解决方法:

    • 进入 Tools->Web Event Recording Configuration..->Custom Settings...中,点击Event->Add添加 ondblclick 鼠标双击操作
    • 脚本中添加 FireEvent("ondblclick")--双击动作,脚本如下:

    Browser("网址").Page("网页").Frame("Frame").WebElement("地区").Click '鼠标单击选定

    Browser("网址").Page("网页").Frame("Frame").WebElement("地区").FireEvent("ondblclick") '鼠标双击操作

     

    1.问题:QTP 脚本中关于ActiveX 控件的加载异常:QTP 弹出一个对话窗口,提示为“当前安全设置禁止运行该页中的ActiveX 控件,因此,该页可能无法正常显示”

    解决方法:进入 Tools->Options->Active Screen 中,勾选“Load ActiveX controls”后,重启QTP进行录制即可。

  • QTP脚本自动添加固定的信息

    2011-10-09 16:37:02

    QTP/dat目录下新建一个 ActionTemplate.MST 文件,文件内容为希望每次都自动显示在脚本开头的信息,如:

    '#################################################################
    '软件版本:
    '测试功能:
    '测试人员:
    '编写日期:
    '修改历史:
    '#################################################################

  • QTP对FireFox的支持【转载】

    2011-10-09 16:14:40

    一、工具版本及设定:

    QTP10 + FireFox3.0.8

    在qtp10的帮助文档中明明很清晰地说明了对FireFox3.0.x的支持,但是开始的时候qtp就是识别不了firefox中的对象,经过多方调查,终于发现需要在FireFox中安装add-on。具体做法如下:

    1.找到AgentPluginInFireFox30文件夹

    我这个qtp10在安装目录的 HP\QuickTest Professional\bin\Mozilla\AgentPluginInFireFox30

    2.将该文件夹拷贝一份到FireFox的Add-on下面

    FireFox的安装目录下的extensions就是FireFox的Add-on目录

    3.修改拷贝到extensions下的AgentPluginInFireFox30文件夹的文件夹名

    在AgentPluginInFireFox30文件夹里面有一个install.rdf文件,该文件中的大概前面几行有一个<em:id>标签,该标签中的值就作为AgentPluginInFireFox30文件夹的文件夹名

    4.重新打开FireFox,并确认是否qtp的Add-on安装成功了

    menu -- 工具 -- add-on中如果出现了QuickTest Professional 10.0 Plugin字样,就说明安装成功了

    5.Object Spy一下你就会发现终于qtp把对象就认识成web的了。啊~世界是如此美好~~~

    附上网上查到的资料:

    http://knowledgeinbox.com/articles/qtp/issues/firefox-is-not-recognized-as-browser-after-upgrade/ 

    http://www.geekinterview.com/talk/14144-qtp-and-firefox.html

     

    二、QTP在能成功识别出FF中网页的对象后,很快你又会发现很郁闷的问题,比如说,当你Object Spy的时候,你会发现在RO的标签中会有这么一句话「実行環境オブジェクトのプロパティは、XXオブジェクトではサポートされていません。」,这个问题直接导致你将不能通过DOM的方式对对象进行操作,比如说我想通过 Browser().Page().object.documentElement.InnerHtml 来取得页面的html,但是直接到.object就挂了。

    不过如果需要取得页面的html的话,不通过DOM对象也能取得,看一段脚本吧。

    set sh = createobject("Wscript.Shell")

    wait(1)

    sh.SendKeys "^u"

    wait(1)

    html = Browser().page().WebElement().GetRoProperty("innerText")

    wait(1)

    HtmlCheckPoint(html,strName)  ⇒ 这个方法可以参考http://hi.baidu.com/qiyongping/blog/item/7917dca7427e8c8cd14358fe.html

    set sh = nothing

    幸好,还是能够得到source窗口的对象,然后可以通过GetRoProperty("innerText")方法来取得html的

     

    三、QTP10帮助文档中明确说名支持3.0.x,但是如果有安装了相应的qtp patch的话,QTP10还能支持FireFox3.5和FireFox3.6

    或许这种patch可以到HP官网上找到。

    http://h30499.www3.hp.com/t5/Functional-and-Business-Process/ct-p/sws-FBPV

     

    四、QTP只能识别在FireFox窗口中显示web页面的对象,对FireFox的其他部分比如地址栏,菜单栏等等都不能识别,不过,似乎IE也是这样的。

     

    五、手机网站的测试中,会用到FireMobileSimulator,这是一个FireFox的add-on,在FMS的官网上,只能下载到最新的版本。而最新的版本可能比较适用于FireFox比较新的版本,比如FireFox4。但是很不幸运的是QTP10对FireFox4不支持。如果你在用FirFox3.0.8测试的话,那么我可以告诉你FireMobileSimulator1.1.11与之是契合的。

    可以取得FireFox以前版本的网站:

    http://www.oldapps.com/firefox.php?old_firefox=56

  • QTP Action0的作用

    2011-10-09 15:39:51

    打开QTP脚本目录,我们可以看到有一个Action0目录,这个并不是我们自己写的,它是干什么用的呢?

    打开这个Action0目录,用文本编辑器打开Script.mts可以看到一条或多条RunAction或Call RunAction

    如:Call RunAction("Sign_In [ActionA]", oneIteration)
       RunAction "Copy of FlightOrder", allIterations
       Call RunAction("ReturnHome [ActionA]", oneIteration)

    对比我们在QTP中用Keyword View查看的Action就可以看出这个结构是与之对应的,显然是与Action调用有关,记录了调用Action的顺序以及循环情况

  • Loadrunner自定义监控器方法

    2011-07-15 12:02:05

    Loadrunner安装目录下 *\dat\monitors\vmon.cfg 该文件中有各监控器的信息,用户也可根据需要手动添加合适的监控器。
  • plsql设置

    2011-05-12 14:22:11

    ORACLE sqlplus set 命令速查

    SQL>set colsep' ';     //-域输出分隔符

    SQL>set echo off;      //显示start启动的脚本中的每个sql命令,缺省为on

    SQL> set echo on;        //设置运行命令是是否显示语句

    SQL> set feedback on;     //设置显示“已选择XX行”

    SQL>set feedback off;    //回显本次sql命令处理的记录条数,缺省为on

    SQL>set heading off;    //输出域标题,缺省为on

    SQL>set pagesize 0;     //输出每页行数,缺省为24,为了避免分页,可设定为0。

    SQL>set linesize 80;    //输出一行字符个数,缺省为80

    SQL>set numwidth 12;     //输出number类型域长度,缺省为10

    SQL>set termout off;    //显示脚本中的命令的执行结果,缺省为on

    SQL>set trimout on;    //去除标准输出每行的拖尾空格,缺省为off

    SQL>set trimspool on;   //去除重定向(spool)输出每行的拖尾空格,缺省为off

    SQL>set serveroutput on; //设置允许显示输出类似dbms_output

    SQL> set timing on;      //设置显示“已用时间:XXXX”

    SQL> set autotrace on-;  //设置允许对执行的sql进行分析

    SQL> set verify off;    //可以关闭和打开提示确认信息old 1和new 1的显示. 

    SQL> SET LONG 1000000;   //将clob字段全部显示

  • 【转载】Loadrunner中web_reg_save_param的使用详解

    2011-04-26 10:28:54

     

    【摘要】利用实际案例说明如何使用Mercury LoadRunner提取包含在HTML页内的动态信息并创建参数。

    【关键词】性能测试,压力测试,Mercury LoadRunner

    • 应用范围

    在使用Loadrunner进行性能测试时,经常遇到一种情况,需要通过web页面修改某事务的状态。于是需要首先读出当前的事务的状态,再进行修改,此时便可以使用到web_reg_save_param了。可以通过它先将事务的状态读出写入一个自定义的变量中,根据变量的值来决定下一步的动作。

    • 简要说明

    语法:

    int web_reg_save_param(const char *ParamName, <list of Attributes>, LAST);

    参数说明:

    • ParamName:存放得到的动态内容的参数名称
    • list of Attributes:其它属性,包括:Notfound, LB, RB, RelFrameID, Search, ORD, SaveOffset, Convert, SaveLen。属性值不分大小写
      • Notfound:当在返回信息中找不到要找的内容时应该怎么处理
      • Notfound=error:当在返回信息中找不到要找的内容时,发出一个错误讯息。这是缺省值。
      • Notfound=warning:当在返回信息中找不到要找的内容时,只发出警告,脚本也会继续执行下去不会中断。
      • LB( Left Boundary ) :返回信息的左边界字串。该属性必须有,并且区分大小写。
      • RB( Right Boundary ):返回信息的右边界字串。该属性必须有,并且区分大小写。
      • RelFrameID:相对于URL而言,欲查找的网页的Frame。此属性质可以是All或是数字,该属性可有可无。
      • Search :返回信息的查找范围。可以是HeadersBodyNoresourceAll(缺省)。该属性质可有可无。
      • ORD :说明第几次出现的左边界子串的匹配项才是需要的内容。该属性可有可无,缺省值是1。如为All,则将所有找到的内容储存起来。
      • SaveOffset :当找到匹配项后,从第几个字元开始存储到参数中。该属性不能为负数,缺省值为0
      • SaveLen:当找到匹配项后,偏移量之后的几个字元存储到参数中。缺省值是-1,表示一直到结尾的整个字串都存入参数。
      • Convert :可取的值有以下两种:

    HTML_TO_URL :HTML-encoded资料转成URL-encoded资料格式

    HTML_TO_TEXT :HTML-encoded资料转成纯文字资料格式

    • 实例讲解

    目的:取得页面中的商品状态,如果状态是正常态就改为注销态,否则改为正常态。

    录制脚本使用的是URL based scrīpt

    将返回的数据记录到日志

    • 直接手工访问页面,检查URL

    该页面上点击右键,选择属性

    看到URL,对照录制下的脚本中有:
    web_url("modifyOfferingStatePage.do",
    "URL={url}/web/businessAccept/order/modifyOfferingStatePage.do?offeringId=
    282172&offeringSpecId=1&offeringSpecName=
    普通宽带(ADSL/LAN&customerName=
    {clientname}&nodeId=260000&pos1=
    定购管理&pos2=修改商品状态",

    "Resource=0",
    "RecContentType=text/html",
    "Referer={url}/web/businessAccept/order/orderMenu.do",
    "Snapshot=t23.inf",
    "Mode=HTTP",
    LAST);
    于是在这段代码前添加注册函数:
    web_reg_save_param("oldstate",
    "LB/IC=
    原有商品状态:</td>",
    "RB/IC=</td>",
    "Search=body",
    "Ord=1",
    "RelFrameId=1",
    "SaveOffset=57",
    "SaveLen=4",
    LAST);
    web_url("modifyOfferingStatePage.do",
    "URL={url}/web/businessAccept/order/modifyOfferingStatePage.do?offeringId=
    282172&offeringSpecId=1&offeringSpecName=
    普通宽带(ADSL/LAN&customerName={clientname}&nodeId=
    260000&pos1=
    定购管理&pos2=修改商品状态",

    "Resource=0",
    "RecContentType=text/html",
    "Referer={url}/web/businessAccept/order/orderMenu.do",
    "Snapshot=t23.inf",
    "Mode=HTTP",
    LAST);
    ...............
    //
    将得到的内容存入日志用于检查
    lr_log_message("getvalue : %s",lr_eval_string ("{oldstate}"));

    if ( lr_eval_string ("{oldstate}") == "正常"){
    web_submit_data("modifyOfferingState.do",
    "Action={url}/web/businessAccept/order/modifyOfferingState.do",
    "Method=POST",
    "RecContentType=text/html",
    "Referer={url}/web/businessAccept/order/modifyOfferingStatePage.do?offeringId=
    282172&offeringSpecId=1&offeringSpecName=
    普通宽带(ADSL/LAN&customerName=
    {clientname}&nodeId=260000&pos1=
    定购管理&pos2=修改商品状态",

    "Snapshot=t24.inf",
    "Mode=HTTP",
    ITEMDATA,
    "Name=offering.state", "Value=1", ENDITEM,
    "Name=offering.recentModifyReason", "Value=
    修改原因", ENDITEM,
    "Name=offering.customerId", "Value=281218", ENDITEM,
    "Name=offering.offeringId", "Value=282172", ENDITEM,
    "Name=offering.offeringSpecId", "Value=1", ENDITEM,
    "Name=offering.recentMender", "Value=root", ENDITEM,
    "Name=offering.recentModifyDatetime", "Value=2005-01-16", ENDITEM,
    "Name=nodeId", "Value=260000", ENDITEM,
    "Name=customerName", "Value={clientname}", ENDITEM,
    "Name=offeringSpecName", "Value=
    普通宽带(ADSL/LAN", ENDITEM,
    "Name=submit.x", "Value=33", ENDITEM,
    "Name=submit.y", "Value=13", ENDITEM,
    LAST);
    }
    Else
    {
    web_submit_data("modifyOfferingState.do",
    "Action={url}/web/businessAccept/order/modifyOfferingState.do",
    "Method=POST",
    "RecContentType=text/html",
    "Referer={url}/web/businessAccept/order/modifyOfferingStatePage.do?offeringId=
    282172&offeringSpecId=1&offeringSpecName=
    普通宽带(ADSL/LAN&customerName=
    {clientname}&nodeId=260000&pos1=
    定购管理&pos2=修改商品状态",

    "Snapshot=t24.inf",
    "Mode=HTTP",
    ITEMDATA,
    "Name=offering.state", "Value=0", ENDITEM,
    "Name=offering.recentModifyReason", "Value=
    修改原因", ENDITEM,
    "Name=offering.customerId", "Value=281218", ENDITEM,
    "Name=offering.offeringId", "Value=282172", ENDITEM,
    "Name=offering.offeringSpecId", "Value=1", ENDITEM,
    "Name=offering.recentMender", "Value=root", ENDITEM,
    "Name=offering.recentModifyDatetime", "Value=2005-01-16", ENDITEM,
    "Name=nodeId", "Value=260000", ENDITEM,
    "Name=customerName", "Value={clientname}", ENDITEM,
    "Name=offeringSpecName", "Value=
    普通宽带(ADSL/LAN", ENDITEM,
    "Name=submit.x", "Value=33", ENDITEM,
    "Name=submit.y", "Value=13", ENDITEM,
    LAST);
    }
    从日志中截取的真实的返回内容为:
    vuser_init.c(689): <tr bgcolor="#F6F6F6">\r\n
    vuser_init.c(689): <td width="30%" height="23" align="right">\r\n
    vuser_init.c(689):
    原有商品状态:</td>\r\n
    vuser_init.c(689): <td width="70%" height="23">
    正常</td>\r\n
    vuser_init.c(689): </tr>\r\n
    vuser_init.c(689): <tr bgcolor="#F4FBFE">\r\n
    vuser_init.c(689): <td width="30%" height="23" align="right">\r\n
    vuser_init.c(689):
    修改后的状态:</td>\r\n
    vuser_init.c(689): <td width="70%" height="23">\r\n
    vuser_init.c(689): \r\n
    vuser_init.c(689): \r\n
    vuser_init.c(689): \r\n
    vuser_init.c(689): <input type="radio" name='offering.state' value='4' checked>
    可以看到左边界是:原有商品状态:</td>
    右边界是:</td>,偏移量为:57(包括了空格),
    长度为:4(因为一个汉字长度为2),最后存入变量的值是:正常

    4.经验总结
    1)
    为了便于脚本的调试,将返回的数据都写入日志是个好办法;
    2)
    为了验证取得的数据是否是自己期望的,可以将取得的数据写入日志中进行验证,
    例:lr_log_message("getvalue : %s",lr_eval_string ("{oldstate}"));
    3)
    因为它是一个注册函数,必须在返回信息前使用,所以注册的位置必须正确,否则很可能得到类似如下错误:
    4)vuser_init.c(734): Error -27190: No match found for the requested parameter "oldstate".
    Check whether the requested boundaries exist in the response data. Also,
    if the data you want to save exceeds 1024 bytes,
    use web_set_max_html_param_len to increase the parameter size [MsgId: MERR-27190]
    5)vuser_init.c(734): Error -27187: The above "not found"
    error(s) may be explained by header and body byte counts being 0 and 0,
    respectively. [MsgId: MERR-27187]
    6)vuser_init.c(734):
    web_concurrent_end highest severity level was "ERROR" [MsgId: MMSG-27181]
    7)
    所以使用手工方法,右键页面确定在代码中哪个位置之前注册函数至关重要
    8)
    如果脚本中中文为乱码,可能是因为源文件的字符集和操作系统字符集不匹配。

     

    转自:http://labs.chinamobile.com/mblog/386547_55544

  • Loadrunner脚本录制时乱码处理

    2011-04-22 10:10:49

    字符串编码转换的函数lr_convert_string_encoding:

    lr_convert_string_encoding ( const char *sourceString, const char *fromEncoding, const char *toEncoding, const char *paramName);

    • sourceString:被转换的源字符串
    • fromEncoding:转换前的字符编码
    • toEncoding:要转换成为的字符编码
    • paramName:转换后的目标字符串

    编码类型:LR_ENC_UTF8,LR_ENC_SYSTEM_LOCALE,LR_ENC_UNICODE

  • 【转贴]】在Loadrunner脚本目录下哪些文件可以删除呢

    2011-04-22 09:34:37

    运行Loadrunner脚本时,会产生与脚本文件名相同的文件夹。当你需要在另一台计算机上运行时,其下的大多数文件是需要的。因此,最简单的做法是把整个文件夹拷过去。如果你想删除一些不必要的文件,你可以删除一些日志和输出文件。
    具体包括:

    options.txt
    mdrv_cmd.txt
    mdrv.log
    debug.inf
    pre_cci.c
    .ci
    combined_.c
    output.txt

    除了以上,还包括所有扩展名为.idx和.bak的文件以及Result1文件夹下的文件和子目录。
    注:如果删除“脚本目录\data文件夹下的RecordingLog.txt”文件,虽然不影响脚本的回放,但是不能
    再看到在录制过程中发生的信息。

    在Loadrunner脚本目录下哪些文件可以删除呢?
    就这个问题而言不是什么问题,因为把整个脚本文件夹移过去,既快又安全。但是,通过了解这些文件,将有助于深入理解Loadrunner工作原理和开发脚本等等。
    为了提高效率,现提供一个批处理文件代替手工删除过程。如果大家发现还可以删除其它文件而不影响在另一台计算机上运行,那么可以不断地补充。具体代码如下: echo off
    cls
    echo.
    echo.
    echo  This batch file will delete the following files from every
    echo  folder and subdirectory from the folder in which it is run:
    echo.  
    echo  *.idx
    echo  mdrv*.log
    echo  mdrv.txt
    echo  options.txt
    echo  *.ci
    echo  combined_*.c
    echo  output.txt
    echo  debug.inf
    echo  *.bak
    echo  \result1
    echo.
    echo.
    if exist %temp%\FilesDeleted.txt del %temp%\FilesDeleted.txt
    del *.idx /s >%temp%\FilesDeleted.txt
    del mdrv*.log /s >>%temp%\FilesDeleted.txt
    del mdrv.txt /s >>%temp%\FilesDeleted.txt
    del options.txt /s >>%temp%\FilesDeleted.txt
    del *.ci /s >>%temp%\FilesDeleted.txt
    del combined_*.c /s >>%temp%\FilesDeleted.txt
    del output.txt /s >>%temp%\FilesDeleted.txt
    del debug.inf /s >>%temp%\FilesDeleted.txt
    del *.bak /s >>%temp%\FilesDeleted.txt
    rd result1 /s /q
    "Notepad.exe" "%temp%\FilesDeleted.txt"
    del %temp%\FilesDeleted.txt
    可以把上述代码存成fileDel.bat或fileDel.cmd,都可以,随大家意。
    最后,对代码稍作解释一下。
    首先,该批处理文件(fileDel.bat)从它所在的目录开始查找上面列出的要删除的文件,在查找之前判断是否存在FileDeleted.txt文件,
    存在则删除。
    其次,如果找到列出文件时,就把该文件删除,并把删除信息输出到FileDeleted.txt。没有找到时就会有找不到 XXX文件
    提示
    最后,当查找结束后会调用记事本打开FileDeleted.txt文件,删除信息一目了然。
    该打住了,不是问题的问题说得太多了。Enjoy!

  • 【转载】Oracle动态性能表——v$sesstat

    2011-04-21 14:39:03

    本文转载自三少的学习笔记  

    按照OracleOnlineBook中的描述,v$sesstat存储sessionloginlogout的详细资源使用统计。

     

    类似于v$sysstat,该视图存储下列类别的统计:

     

    l         事件发生次数的统计,如用户提交数。

    l         数据产生,存取或者操作的total(如:redo size)

    l         执行操作所花费的时间累积,例如session CPU占用(如果TIMED_STATISTICS值为true)

    注意:

    如果初始参数STATISTICS_LEVEL被设置为TYPICALALL,时间统计被数据库自动收集如果STATISTICS_LEVEL被设置为BASIC,你必须设置TIMED_STATISTICS值为TRUE以打开收集功能。

     

    如果你已设置了DB_CACHE_ADVICE,TIMED_STATISTICSTIMED_OS_STATISTICS,或在初始参数文件或使用ALTER_SYSTEMALTER SESSION,那么你所设定的值的值将覆盖STATISTICS_LEVEL的值。

     

    v$sysstatv$sesstat差别如下:

    n         v$sesstat只保存session数据,而v$sysstat则保存所有sessions的累积值。

    n         v$sesstat只是暂存数据,session退出后数据即清空。v$sysstat则是累积的,只有当实例被shutdown才会清空。

    n         v$sesstat不包括统计项名称,如果要获得统计项名称则必须与v$sysstatv$statname连接查询获得。

     

    v$sesstat可被用于找出如下类型session

    n         高资源占用

    n         高平均资源占用比(登陆后资源使用率)

    n         默认资源占用比(两快照之间)

     

    V$SESSTAT中使用统计

      多数v$sesstat中的统计参考是v$sysstat描述的子集,包括session logical reads, CPU used by this session, db block changes, redo size, physical writes, parse count (hard), parse count (total), sorts (memory), and sorts (disk).

     

    V$SESSTAT常用列说明

    n         SIDsession唯一ID

    n         STATISTIC#:资源唯一ID

    n         VALUE:资源使用

     

     

    示例1:下列找出当前session中最高的logicalPhysical I/O比率.

     

      下列SQL语句显示了所有连接到数据库的session逻辑、物理读比率(每秒)logicalphysical I/O比率是通过自登陆后的时间消耗计算得出。对于sessions连接到数据库这种长周期操作而言也许不够精确,不过做个示例却足够了。

     

    先获得session逻辑读和物理读统计项的STATISTIC#值:

    SELECT name, statistic#

      FROM V$STATNAME

      WHERE name IN ('session logical reads','physical reads') ;

    NAME                           STATISTIC#

    ------------------------------ ----------

    session logical reads                   9

    physical reads                        54

     

    通过上面获得的STATISTIC#值执行下列语句:

     

    SELECT ses.sid

         , DECODE(ses.action,NULL,'online','batch')          "User"

         , MAX(DECODE(sta.statistic#,9,sta.value,0))

           /greatest(3600*24*(sysdate-ses.logon_time),1)     "Log IO/s"

         , MAX(DECODE(sta.statistic#,54,sta.value,0))

           /greatest(3600*24*(sysdate-ses.logon_time),1)     "Phy IO/s"

         , 60*24*(sysdate-ses.logon_time)                    "Minutes"

     FROM V$SESSION ses

        , V$SESSTAT sta

    WHERE ses.status     = 'ACTIVE'

      AND sta.sid        = ses.sid

      AND sta.statistic# IN (9,54)

    GROUP BY ses.sid, ses.action, ses.logon_time  <== 先按sid分组,再按action分组,最后按登录时间分组

    ORDER BY

            SUM( DECODE(sta.statistic#,54,100*sta.value,sta.value) )

          / greatest(3600*24*(sysdate-ses.logon_time),1)  DESC;

     

      SID User   Log IO/s Phy IO/s Minutes

    ----- ------ -------- -------- -------

     1951 batch       291    257.3       1

      470 online    6,161     62.9       0

      730 batch     7,568     43.2     197

     2153 online    1,482     98.9      10

     2386 batch     7,620     35.6      35

     1815 batch     7,503     35.5      26

     1965 online    4,879     42.9      19

     1668 online    4,318     44.5       1

     1142 online      955     69.2      35

     1855 batch       573     70.5       8

     1971 online    1,138     56.6       1

     1323 online    3,263     32.4       5

     1479 batch     2,857     35.1       3

      421 online    1,322     46.8      15

     2405 online      258     50.4       8

    Tips:

    Ø         DECODE函数

    语法:DECODE(条件表达式,值,返回值1,返回值2)

    解释:当“条件表达式”计算出来的结果等于“值”,那么返回“返回值1”否则返回“返回值2

    Ø         MAX函数可以返回一组数值中的最大值,忽略逻辑值和文本字符

    Ø         greatest( expr1, expr2, ... expr_n )

    expr1, expr2, . expr_n 可以值也可以是函数.

    函数功能:  取得值最大值。

    影响版本:Oracle 8i, Oracle 9i, Oracle 10g, Oracle 11g

    例子:

    greatest(2, 5, 12, 3) would return 12

    greatest('2', '5', '12', '3') would return '5'

    greatest('apples', 'oranges', 'bananas') would return 'oranges'

    greatest('apples', 'applis', 'applas') would return 'applis'

     

    示例2:又例如通过v$sesstatv$statname连接查询某个SID各项信息。

    select a.*,b.name

      from v$sesstat a,v$statname b

      where a.sid=164 and a.statistic#=b.statistic#;

     

    group by 的用法:

    http://bkeep.blog.163.com/blog/static/1234142902010220104316786

    http://bkeep.blog.163.com/blog/static/1234142902010220104140682

  • 【转载】Oracle动态性能表——v$sysstat

    2011-04-21 14:36:29

    一,类似于V$SESSTAT,该视图存储下列的统计信息: 1
    1>.事件发生次数的统计(如:user commits) 1
    2>.数据产生,存取或者操作的total列(如:redo size) 1
    3>.如果TIMED_STATISTICS值为true,则统计花费在执行操作上的总时间(如:CPU used by this session) 1
    二,V$SYSSTAT视图常用列介绍: 1
    该视图还有一列class-统计类别但极少会被使用,各类信息如下: 1
    三,使用V$SYSSTAT中的数据 2
    3.1 v$sysstat功能概述 2
    3.2数据库使用状态的一些关键指标: 2
    3.3 SQL语句解析过程 3
    3.4 物理I/O 3
    四,V$SYSSTAT典型应用 3
    4.1由V$SYSSTAT得出实例效率比(Instance Efficiency Ratios) 3
    4.2 Buffer cache hit ratio:该项显示buffer cache大小是否合适。 3
    4.3 Soft parse ratio:这项将显示系统是否有太多硬解析。 3
    4.4 In-memory sort ratio:该项显示内存中完成的排序所占比例。 4
    4.5 Parse to execute ratio:在生产环境,最理想状态是一条sql语句一次解析多数运行。 4
    4.6 Parse CPU to total CPU ratio:该项显示总的CPU花费在执行及解析上的比率。 4
    4.7 Parse time CPU to parse time elapsed:通常,该项显示锁竞争比率。 4
    五,从V$SYSSTAT获取负载间档(LOAD PROFILE)数据 4
    5.0 概述 4
    5.2 Blocks changed for each read:这项显示出block changes在block reads中的比例。 5
    5.3 Rows for each sort: 5

     

    正文:

    文档下载:http://www.itpub.net/782892.html

    v$sysstat存储自数据库实例运行起就开始累计全实例(instance-wide)的资源使用情况。

    一,类似于v$sesstat,该视图存储下列的统计信息:

    1>.事件发生次数的统计(如:user commits)
    2>.数据产生,存取或者操作的total(如:redo size)
    3>.如果TIMED_STATISTICS值为true,则统计花费在执行操作上的总时间(如:CPU used by this session)

     

    二,v$sysstat视图常用列介绍:

    STATISTIC#: 标识
    NAME:
    统计项名称
    VALUE:
    资源使用量

    该视图还有一列class-统计类别但极少会被使用,各类信息如下:

    1 代表事例活动
    2
    代表Redo buffer活动
    4
    代表锁
    8
    代表数据缓冲活动
    16
    代表OS活动
    32
    代表并行活动
    64
    代表表访问
    128
    代表调试信息
    注意:Statistic#的值在不同版本中各不相同,使用时要用Name做为查询条件而不要以statistic#的值做为条件。

    三,使用v$sysstat中的数据

    3.1 v$sysstat功能概述

      该视图中数据常被用于监控系统性能。如buffer cache命中率、软解析率等都可从该视图数据计算得出。
      该视图中的数据也被用于监控系统资源使用情况,以及系统资源利用率的变化。正因如此多的性能数据,检查某区间内系统资源使用情况可以这样做,在一个时间段开始时创建一个视图数据快照,结束时再创建一个,二者之间各统计项值的不同(end value - begin value)即是这一时间段内的资源消耗情况。这是oracle工具的常用方法,诸如Statspack以及BSTAT/ESTAT都是如此。
      为了对比某个区间段的数据,源数据可以被格式化(每次事务,每次执行,每秒钟或每次登陆),格式化后数据更容易从两者中鉴别出差异。这类的对比在升级前,升级后或仅仅想看看一段时间内用户数量增长或数据增加如何影响资源使用方面更加实用。
      你也可以使用v$sysstat数据通过查询v$system_event视图来检查资源消耗和资源回收。

    V$SYSSTAT中的常用统计

      V$SYSSTAT中包含多个统计项,这部分介绍了一些关键的v$sysstat统计项,在调优方面相当有用。下列按字母先后排序:

    3.2数据库使用状态的一些关键指标:

    CPU used by this session:所有sessioncpu占用量,不包括后台进程。这项统计的单位是百分之x.完全调用一次不超过10ms
    db block changes
    那部分造成SGA中数据块变化的insert,updatedelete操作数
    这项统计可以大概看出整体数据库状态。在各项事务级别,这项统计指出脏缓存比率。单位是:块
    execute count
    执行的sql语句数量(包括递归sql)
    logons current
    当前连接到实例的Sessions。如果当前有两个快照则取平均值。

    logons cumulative
    自实例启动后的总登陆次数。
    parse count (hard)
    shared pool中解析调用的未命中次数。当sql语句执行并且该语句不在shared pool或虽然在shared pool但因为两者存在部分差异而不能被使用时产生硬解析。如果一条sql语句原文与当前存在的相同,但查询表不同则认为它们是两条不同语句,则硬解析即会发生。硬解析会带来cpu和资源使用的高昂开销,因为它需要oracleshared pool中重新分配内存,然后再确定执行计划,最终语句才会被执行。单位:解析次数
    parse count (total)
    :解析调用总数,包括软解析和硬解析。当session执行了一条sql语句,该语句已经存在于shared pool并且可以被使用则产生软解析。当语句被使用(即共享) 所有数据相关的现有sql语句(如最优化的执行计划)必须同样适用于当前的声明。这两项统计可被用于计算软解析命中率。单位:解析次数
    parse time cpu
    cpu解析时间(单位:10ms)。包括硬解析和软解析。
    parse time elapsed
    完成解析调用的总时间花费。
    physical reads
    OS blocks read数。包括插入到SGA缓存区的物理读以及PGA中的直读这项统计并非i/o请求数。

    单位:OS blocks
    physical writes
    SGA缓存区被DBWR写到磁盘的数据块以及PGA进程直写的数据块数量。单位:数据块
    redo log space requests
    redo logs中服务进程的等待空间,表示需要更长时间的log switch
    redo size
    redo发生的总次数(以及因此写入log buffer)byte为单位。这项统计显示出update活跃性。
    session logical reads
    逻辑读请求数。
    sorts (memory)
    sorts(memory)是适于在SORT_AREA_SIZE(因此不需要在磁盘进行排序)的排序操作的数量。

    sorts (disk)sorts(disk)则是由于排序所需空间太大,SORT_AREA_SIZE不能满足而不得不在磁盘进行排序操作的数量。这两项统计通常用于计算in-memory sort ratio
    sorts (rows):
    列排序总数。这项统计可被'sorts (total)'统计项除尽以确定每次排序的列。该项可指出数据卷和应用特征。
    table fetch by rowid
    使用ROWID返回的总列数(由于索引访问或sql语句中使用了'where rowid=&rowid'而产生)
    table scans rows gotten
    :全表扫描中读取的总列数

    table scans blocks gotten
    全表扫描中读取的总块数,不包括那些split的列。
    user commits + user rollbacks
    :系统事务起用次数。当需要计算其它统计中每项事务比率时该项可以被做为除数。例如,计算事务中逻辑读,可以使用下列公式:session logical reads / (user commits + user rollbacks)

    3.3 SQL语句解析过程

    注:SQL语句的解析有软解析soft parse与硬解析hard parse之说,以下是5个步骤:
    1
    :语法是否合法(sql写法)
    2
    :语义是否合法(权限,对象是否存在)
    3
    :检查该sql是否在公享池中存在
    --
    如果存在,直接跳过45,运行sql. 此时算soft parse
    4
    :选择执行计划
    5
    :产生执行计划
    --
    如果5个步骤全做,这就叫hard parse.

    3.4 物理I/O

    注:注意物理I/O

      oracle报告物理读也许并未导致实际物理磁盘I/O操作。这完全有可能因为多数操作系统都有缓存文件,可能是那些块在被读取。块也可能存于磁盘或控制级缓存以再次避免实际I/OOracle报告有物理读也许仅仅表示被请求的块并不在缓存中。

    四,V$SYSSTAT典型应用

    4.1V$SYSSTAT得出实例效率比(Instance Efficiency Ratios)

    下列是些典型的instance efficiency ratios v$sysstat数据计算得来,每项比率值应该尽可能接近1

    4.2 Buffer cache hit ratio:该项显示buffer cache大小是否合适。

    公式:1-((physical reads-physical reads direct-physical reads direct (lob)) / session logical reads)
    执行:

    select 1-((a.value-b.value-c.value)/d.value)
    from v$sysstat a,v$sysstat b,v$sysstat c,v$sysstat d
    where a.name='physical reads' and
    b.name='physical reads direct' and
    c.name='physical reads direct (lob)' and
    d.name='session logical reads';

    4.3 Soft parse ratio:这项将显示系统是否有太多硬解析。

    该值将会与原始统计数据对比以确保精确。例如,软解析率仅为0.2则表示硬解析率太高。不过,如果总解析量(parse count total)偏低,这项值可以被忽略。
    公式:1 - ( parse count (hard) / parse count (total) )
    执行:

    select 1-(a.value/b.value)
    from v$sysstat a,v$sysstat b
    Where a.name='parse count (hard)' and b.name='parse count (total)';

    4.4 In-memory sort ratio:该项显示内存中完成的排序所占比例。

    最理想状态下,在OLTP系统中,大部分排序不仅小并且能够完全在内存里完成排序。
    公式:sorts (memory) / ( sorts (memory) + sorts (disk) )
    执行:

    select a.value/(b.value+c.value)
    from v$sysstat a,v$sysstat b,v$sysstat c
    where a.name='sorts (memory)' and
    b.name='sorts (memory)' and c.name='sorts (disk)';

    4.5 Parse to execute ratio:在生产环境,最理想状态是一条sql语句一次解析多数运行。

    公式:1 - (parse count/execute count)
    执行:

    select 1-(a.value/b.value)
    from v$sysstat a,v$sysstat b
    where a.name='parse count (total)' and b.name='execute count';

    4.6 Parse CPU to total CPU ratio:该项显示总的CPU花费在执行及解析上的比率。

    如果这项比率较低,说明系统执行了太多的解析。
    公式:1 - (parse time cpu / CPU used by this session)
    执行:

    select 1-(a.value/b.value)
    from v$sysstat a,v$sysstat b
    where a.name='parse time cpu' and
    b.name='CPU used by this session';

    4.7 Parse time CPU to parse time elapsed:通常,该项显示锁竞争比率。

    把解析任务交给cpu后,1cpu花时间去解析;2cpu等待(由于锁的原因)

    公式:parse time cpu / parse time elapsed
    执行:

    select a.value/b.value
    from v$sysstat a,v$sysstat b
    where a.name='parse time cpu' and b.name='parse time elapsed';

     

    五,从V$SYSSTAT获取负载间档(Load Profile)数据

    5.0 概述

      负载间档是监控系统吞吐量和负载变化的重要部分,该部分提供如下每秒和每个事务的统计信息:logons cumulative, parse count (total), parse count (hard), executes, physical reads, physical writes, block changes, and redo size.

    被格式化的数据可检查'rates'是否过高,或用于对比其它基线数据设置为识别system profile在期间如何变化。例如,5.1 计算每个事务中block changes可用如下公式:

    db block changes / ( user commits + user rollbacks )
    执行:

    select a.value/(b.value+c.value)
    from v$sysstat a,v$sysstat b,v$sysstat c
    where a.name='db block changes' and
    b.name='user commits' and c.name='user rollbacks';


    5.2 Blocks changed for each read
    :这项显示出block changesblock reads中的比例。

    它将指出是否系统主要用于只读访问或是主要进行诸多数据操作(如:inserts/updates/deletes)
    公式:db block changes / session logical reads
    执行:

    select a.value/b.value
    from v$sysstat a,v$sysstat b
    where a.name='db block changes' and
    b.name='session logical reads' ;

    5.3 Rows for each sort

    公式:sorts (rows) / ( sorts (memory) + sorts (disk) )
    执行:

    select a.value/(b.value+c.value)
    from v$sysstat a,v$sysstat b,v$sysstat c
    where a.name='sorts (rows)' and
    b.name='sorts (memory)' and c.name='sorts (disk)';

621/41234>
Open Toolbar