[20170426]漫长的测试时间.txt

[20170426]漫长的测试时间.txt

--//昨天浏览一个blog,链接nimishgarg.blogspot.com/2015/11/plsql-tuning-bind-variables-and-execute.html
--//里面提到主要是绑定变量的问题,让我感到奇怪的是对方的测试时间:Elapsed: 00:27:15.55(在不使用绑定变量的情况下).
--//这个时间也太长了,我以前也做过了类似测试执行2万次sql语句大约10秒上下,这样对于他建立的测试例子最多在1分钟之内.
--//换1个想法,我们生产系统每秒的执行语句可以达到3000条(当然混合绑定与非绑定),这样100000/3000=33.3秒,最多1分钟。
--//于是我决定重复测试看看.

1.环境:
SCOTT@book> @ &r/ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

create table test_bind as select level col from dual connect by level <= 2e4;
create index test_indx on test_bind(col);

--//注建立2万行记录(作者1e6条记录),担心测试时间太长.
--//建立测试脚本:

$ cat b1.sql
set timing on
alter system flush shared_pool;
declare
a number;
begin
for i in 1 .. 2e4 loop
execute immediate 'select col from test_bind where col = ' || i into a;
end loop;
end;
/
set timing off

$ cat b2.sql
set timing on
alter system flush shared_pool;
declare
a number;
begin
for i in 1 .. 2e4 loop
execute immediate 'select col from test_bind where col = :i ' into a using i;
end loop;
end;
/
set timing off
--//注,我采用for 循环,实际上与他采用的算法相差不大。

2.测试:
SCOTT@book> @ b1.sql
System altered.
Elapsed: 00:00:00.14
PL/SQL procedure successfully completed.
Elapsed: 00:00:45.36

--//45*5=225秒,不知道作者如何27分钟。但是还是与我想像存在差距,我记得我以前测试1万条这样sql语句4秒上下,也就是我的测试应该在10秒完成,
--//而现在45秒,还是有点长。

SCOTT@book> @ b2.sql
System altered.
Elapsed: 00:00:00.14
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.59
--//而使用绑定变量不到1秒(放大5倍,5秒),对方也是5秒,基本一致。

3.再仔细看看,发现对方建立的索引不是唯一.难道是问题出在这里吗?
drop index test_indx;
create unique index test_indx on test_bind(col);

--//继续重复测试:
SCOTT@book> @ b1
System altered.
Elapsed: 00:00:00.12
PL/SQL procedure successfully completed.
Elapsed: 00:00:10.19

--//10秒。

4.问题似乎到这里可以定位问题在于索引的建立方式,再仔细想感觉不对,表仅仅一个字段,也就是生成的执行计划根本不会访问表,
  虽然唯一索引与非唯一索引的差别是逻辑读相差1个,这样也就是相差2万个逻辑读,这些逻辑读目前的硬件1秒之内就可以访问完成,
  何况我的测试是单用户测试.不存在latch争用问题.看看执行计划:

drop index test_indx;
create index test_indx on test_bind(col);

SCOTT@book> alter session set statistics_level =all ;

Session altered.

SCOTT@book> select col from test_bind where col=100;
       COL
----------
       100

SCOTT@book> @&r/dpc '' '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  bm4df1k084wcw, child number 0
-------------------------------------
select col from test_bind where col=100
Plan hash value: 4214624029
------------------------------------------------------------------------------------------------------------------------
| Id  | Operation        | Name      | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |           |      1 |        |       |     1 (100)|          |      1 |00:00:00.01 |       3 |
|*  1 |  INDEX RANGE SCAN| TEST_INDX |      1 |      1 |    13 |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       3 |
------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / TEST_BIND@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("COL"=100)

Note
-----
   - dynamic sampling used for this statement (level=2)

--//仔细看执行计划就明白了,问题出在作者没有分析表.在执行过程中存在动态取样.
--//退出在登陆,避免statistics_level =all 影响。

SCOTT@book> show parameter sampling
NAME                       TYPE     VALUE
-------------------------- -------- ------
optimizer_dynamic_sampling integer  2

SCOTT@book> alter session set optimizer_dynamic_sampling=0;
Session altered.

SCOTT@book> @ b1
System altered.
Elapsed: 00:00:00.16
PL/SQL procedure successfully completed.
Elapsed: 00:00:10.13

--//可以发现关闭动态取样,现在恢复到10秒。
--//重新分析表再测试:
execute sys.dbms_stats.gather_table_stats ( OwnName => nvl('',user),TabName => 'test_bind',Estimate_Percent => NULL,Method_Opt => 'FOR ALL COLUMNS SIZE 1 ',Cascade => True ,No_Invalidate => false);

SCOTT@book> show parameter sampling
NAME                       TYPE     VALUE
-------------------------- -------- -----
optimizer_dynamic_sampling integer  2

SCOTT@book> @b1
System altered.
Elapsed: 00:00:00.16
PL/SQL procedure successfully completed.
Elapsed: 00:00:10.06

--//可以发现如果没有动态分析,执行都是在10秒完成,换一句话如果执行对方的测试,在99999次循环的情况下,最多1分钟完成任务。
SCOTT@book> execute sys.dbms_stats.delete_table_stats (ownname=> user ,tabname=> 'test_bind',cascade_columns=> true,cascade_indexes=> true,cascade_parts=>true,no_invalidate=> false)
PL/SQL procedure successfully completed.

--//附上存在动态取样的perf top输出:
# perf top -k /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle

PerfTop:    1219 irqs/sec  kernel:16.1%  exact:  0.0% [1000Hz cycles],  (all, 24 CPUs)
---------------------------------------------------------------------------------------------------------
          samples  pcnt function                     DSO
          _______ _____ ____________________________ ____________________________________________________

          2723.00 21.3% evadcd                       /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle
          2259.00 17.6% qesaFastAggNonDistSS         /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle
          2144.00 16.7% lnxsum                       /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle
           764.00  6.0% kdstf00001010000km           /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle
           669.00  5.2% kaf4reasrp0km                /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle

--//分析表之后的perf top输出:
# perf top -k /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle
PerfTop:    1057 irqs/sec  kernel:15.9%  exact:  0.0% [1000Hz cycles],  (all, 24 CPUs)
---------------------------------------------------------------------------------------------------------

          samples  pcnt function                     DSO
          _______ _____ ____________________________ ____________________________________________________

           243.00  4.3% kghalf                       /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle
           241.00  4.2% qksbgGetVal                  /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle
           209.00  3.7% __intel_new_memset           /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle
           169.00  3.0% qksbgGetAltered              /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle
           119.00  2.1% kghfnd                       /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle
           113.00  2.0% kghalo                       /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/oracle

--//可以发现动态取样大量调用evadcd,lnxsum内部函数。

5.你也许要问为什么建立唯一索引后问题消失呢?
--//实际上建立唯一索引后,执行计划不在动态取样,这样消耗缺少了动态取样部分,问题也随之消失.

SCOTT@book> execute sys.dbms_stats.delete_table_stats (ownname=> user ,tabname=> 'test_bind',cascade_columns=> true,cascade_indexes=> true,cascade_parts=>true,no_invalidate=> false)
PL/SQL procedure successfully completed.

SCOTT@book> drop index test_indx;
Index dropped.

SCOTT@book> create unique index test_indx on test_bind(col);
Index created.

SCOTT@book> alter session set statistics_level =all ;
Session altered.

SCOTT@book> select col from test_bind where col=100;
       COL
----------
       100

SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  bm4df1k084wcw, child number 0
-------------------------------------
select col from test_bind where col=100
Plan hash value: 1159737204
----------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation         | Name      | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |
----------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |      1 |        |       |     1 (100)|          |      1 |00:00:00.01 |       2 |      4 |
|*  1 |  INDEX UNIQUE SCAN| TEST_INDX |      1 |      1 |    13 |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       2 |      4 |
----------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / TEST_BIND@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("COL"=100)
23 rows selected.

--//唯一索引的情况下没有动态取样。这样问题自然消失。
--//我在想下次再给开发演示,故意不分析表看看,人为夸大不使用绑定变量的危害,^_^。不然开发真的不长记性,就是一群长不大的孩子.........

时间: 2024-10-17 08:50:09

[20170426]漫长的测试时间.txt的相关文章

[20170426]为什么是4秒.txt

[20170426]为什么是4秒.txt --//在开发程序时我一般会强调开发尽量不要写一些自定义函数,往往可能导致CPU忙.今天测试遇到一个问题: --//原始的测试来之nimishgarg.blogspot.com/2016/03/avoiding-unnecessary-function-calls-to.html --//先重复测试. 1.环境: SCOTT@book> @ &r/ver1 PORT_STRING                    VERSION        B

[20170909]为什么是12秒.txt

[20170909]为什么是12秒.txt --//在开发程序时我一般会强调开发尽量不要写一些自定义函数,往往可能导致CPU忙. --//例子很像这样: CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE)    RETURN dept.dname%TYPE IS    l_dname   dept.dname%TYPE; BEGIN    DBMS_LOCK.sleep (1);    SELECT dname     

wince下,使用C# ,把数据写入txt文件中

问题描述 wince下,使用C# ,把数据写入txt文件中 各位高手大家好,我在wince下,使用C# ,把数据写入txt文件中,所有的代码都执行完成,也没有发生任何错误,但是我打开txt里面是空白的,没有任何数据,不知其解,望高手不吝指教,谢谢.写入txt的代码如下: FileStream fs = null; StreamWriter sw = null; try { fs = new FileStream(fileName, FileMode.Append, FileAccess.Writ

教你快速将多个TXT文档合并成一个

网上下载的文件常常会分割成好几个文件,阅读起来非常不便,本教程为大家介绍如何快速将多个txt文件合并. 文档合并成一个-快速合并word文档"> 同时选定需要合并的txt文档进行压缩 步骤1:首先选中需要合并的多个TXT文档,然后单击鼠标右键,在弹出的菜单中选中"Win-RAR-添加到压缩文件"命令,这时会出现"压缩文件名和参数"窗口,在"常规"标签页中对压缩文件进行命名,并将"压缩方式"下拉框中的"

txt文件-c++如何控制文件输出的行数?

问题描述 c++如何控制文件输出的行数? 我有一个几千行的txt文件,里面都是ascall字符,我想每次读取30行在控制台显示然后清屏,延迟0.1s后再输出接下来的30行,也就是第一次控制台输出1-30行,清屏,第二次输出31-60行,这样一直下去,直到文件末尾 1. 我希望在每次在控制台显示的时候一次性显示30行的字符,必须一次性显示30行,肉眼不能察觉到是一行一行显示出来的. 解决方案 自己做个计数就好了,30行后,计数清零,重新计数 解决方案二: #include #include #in

如何在java中实现读取一个txt文档中的随机一行

问题描述 如何在java中实现读取一个txt文档中的随机一行 如题,如何在java中实现读取一个txt文档中的随机一行? 主要就是怎么随机读取 解决方案 根据楼上的说法,来总结一下吧,总体来说,就是将文件全部都读取出来,每一行存储到一个数组或集合中,然后再通过产生随机数,来对这个数组或是 集合进行随机的访问.这样一来就解决了 解决方案二: 文本文件只能顺序读,不能随机读.你的需求只能是读取文本文件每一行到一个arraylist,然后得到下标范围,产生一个随机数,取那一行 解决方案三: http:

Word文档批量转换成TXT格式的技巧

使用Word编辑文档的时候,不仅可以保存成Word格式,也可以保存为其它格式.但有的时候需要将大批的已经编辑完成的Word文档转换成文本格式或其他格式文档,怎么办?如果通过"另存为"将是一件十分费时费力的事情. 可能有人说了利用第三方工具软件吧,那是另一话题.在这里笔者要告诉大家的是:批量转换文档格式不求"人",完全可以借助Word本身自带的功能就可以完成批量转换文档格式的工作.为了叙述方便,专家以将Word文档格式批量转换成TXT文本格式为例来介绍其转换过程,具体

C++ 怎么向一个txt文件的指定位置添加文本而不覆盖原有的内容?

问题描述 C++ 怎么向一个txt文件的指定位置添加文本而不覆盖原有的内容? 比如说有一个有文本的txt文件,我要在文本中间添加新文本,怎么做才能不覆盖原来的文本? 解决方案 文件追加,append 解决方案二: http://wenwen.sogou.com/z/q553022171.htmhttp://bbs.csdn.net/topics/390533611 这里有两个链接你看看对你有没有帮助 解决方案三: 以append方式打开 如果是想在一段内容中插入新的内容,就必须先保留插入位置以后

mfc 如何把变量的值用txt输出zzzz,,,,,,,,,,,

问题描述 mfc 如何把变量的值用txt输出zzzz,,,,,,,,,,, mfc 如何把变量的值用txt输出,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 解决方案 char* pszFileName="x:\text.txt; CStdioFile myFile; CFileException fileException; if( myFile.Open(pszFileName,CFile::typeText|CFile::modeCreate|CFile::mo