您的位置:首页 > 其它

【性能优化】 之 变量邦定

2014-01-23 13:58 99 查看
1.用示例说明绑定变量的应用领域是OLTP而不是OLAP。<br>

2.用示例演示一次硬分析(hard parse)和一次软分析(soft parse),以及一次更软的分析(softer soft parse),并对给出演示结果。<br>

3.用示例演示一次分析,多次执行的示例,并对给出演示结果。<br>

4.演示一个父游标产生3个子游标的示例,并分别说明每个子游标产生的原因。<br>

5.演示ACS(adaptiver cursor sharing)的效果。<br>

==================================================================================

1.用示例说明绑定变量的应用领域是OLTP而不是OLAP。<br>

答:

1.1 示例说明

SQL> drop table t1 purge;

Table dropped.

SQL> create table t1 as select * from dba_objects;

Table created.

SQL> alter session set tracefile_identifier='bind_var';

Session altered.

SQL> alter session set sql_trace=true;

Session altered.

SQL> begin

2 for i in 1..100 loop

3 execute immediate 'select * from t1 where object_id=:i' using i;

4 end loop;

5 end;

6 /

PL/SQL procedure successfully completed.

SQL> alter session set sql_trace=false;

Session altered.

SQL> select sql_text,pase_calls,loads,executions from v$sql where sql_text like 'select * from t1 where %';

select sql_text,pase_calls,loads,executions from v$sql where sql_text like 'select * from t1 where %'

*

ERROR at line 1:

ORA-00904: "PASE_CALLS": invalid identifier

SQL> select sql_text,parse_calls,loads,executions from v$sql where sql_text like 'select * from t1%';

SQL_TEXT PARSE_CALLS LOADS EXECUTIONS

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

select * from t1 where object_id=:i 1 1 100

从上面的查询中,可以看到,在重复执行了100次的查询中,有1次的硬解析,

1.2 下面再进行一个非绑定变量的SQL 执行情况:

SQL> alter session set sql_trace=true; 启动trace功能

Session altered.

SQL> begin

for i in 1..100 loop

execute immediate 'select * from T where object_id='||i;

end loop;

end;

/

PL/SQL procedure successfully completed.

我们对一条sql执行了100次没有采用绑定变量技术,oracle对这条sql要硬解析100次,执行100次,CPU的消耗就有了100次。

SQL> alter session set sql_trace=false; 关闭trace功能

Session altered.

LEO1@LEO1> select sql_text,parse_calls,loads,executions from v$sql where sql_text like 'select * from T1 where %' order by 1;

SQL_TEXT PARSE_CALLS LOADS EXECUTIONS

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

select * from t1 where object_id=1 1 1 1

....

select * from t1 where object_id=100 1 1 1

100 rows selected.

SQL>

再来查看一下跟踪文件:

1.3 使用绑定变量跟踪部分:

D:\app\oracle\diag\rdbms\orcl\orcl\trace>tkprof orcl_ora_5528_bind_var.trc out_b

ind.log

TKPROF: Release 11.2.0.3.0 - Development on 星期四 12月 5 17:58:35 2013

Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.

SQL ID: 28gj7tsy13xq8 Plan Hash: 3617692013

select *

from

t1 where object_id=:i

call count cpu elapsed disk query current rows

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

Parse 1 0.00 0.00 0 0 0 0

Execute 100 0.01 0.00 0 1 0 0

Fetch 0 0.00 0.00 0 0 0 0

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

total 101 0.01 0.00 0 1 0 0

Misses in library cache during parse: 1

Optimizer mode: ALL_ROWS

Parsing user id: 84 (recursive depth: 1)

Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation

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

0 0 0 TABLE ACCESS FULL T1 (cr=0 pr=0 pw=0 time=3 us cost=305 size=2484 card=12)

********************************************************************************

1.4 没使用绑定变量跟踪部分:

begin

for i in 1..100 loop

execute immediate 'select * from t1 where object_id='||i;

end loop;

end;

call count cpu elapsed disk query current rows

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

Parse 1 0.00 0.00 0 0 0 0

Execute 1 0.00 0.01 0 0 0 1

Fetch 0 0.00 0.00 0 0 0 0

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

total 2 0.00 0.02 0 0 0 1

Misses in library cache during parse: 1

Optimizer mode: ALL_ROWS

Parsing user id: 84

********************************************************************************

SQL ID: 9vx4vjbr7qrnn Plan Hash: 2586623307

SELECT /* OPT_DYN_SAMP */ /*+ ALL_ROWS IGNORE_WHERE_CLAUSE

NO_PARALLEL(SAMPLESUB) opt_param('parallel_execution_enabled', 'false')

NO_PARALLEL_INDEX(SAMPLESUB) NO_SQL_TUNE */ NVL(SUM(C1),:"SYS_B_0"),

NVL(SUM(C2),:"SYS_B_1")

FROM

(SELECT /*+ IGNORE_WHERE_CLAUSE NO_PARALLEL("T1") FULL("T1")

NO_PARALLEL_INDEX("T1") */ :"SYS_B_2" AS C1, CASE WHEN "T1"."OBJECT_ID"=

:"SYS_B_3" THEN :"SYS_B_4" ELSE :"SYS_B_5" END AS C2 FROM "TANG"."T1"

SAMPLE BLOCK (:"SYS_B_6" , :"SYS_B_7") SEED (:"SYS_B_8") "T1") SAMPLESUB

call count cpu elapsed disk query current rows

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

Parse 100 0.00 0.01 0 0 0 0

Execute 100 0.00 0.00 0 0 0 0

Fetch 100 0.18 0.16 0 6900 0 100

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

total 300 0.18 0.17 0 6900 0 100

Misses in library cache during parse: 1

Misses in library cache during execute: 1

Optimizer mode: ALL_ROWS

Parsing user id: 84 (recursive depth: 2)

Number of plan statistics captured: 3

Rows (1st) Rows (avg) Rows (max) Row Source Operation

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

1 1 1 SORT AGGREGATE (cr=69 pr=0 pw=0 time=1701 us)

4452 4452 4452 TABLE ACCESS SAMPLE T1 (cr=69 pr=0 pw=0 time=4608 us cost=19 size=128650 card=5146)

********************************************************************************

SQL ID: d44dqxf5hgz0j Plan Hash: 3617692013

select *

from

t1 where object_id=1

call count cpu elapsed disk query current rows

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

Parse 1 0.00 0.00 0 1 0 0

Execute 1 0.00 0.00 0 0 0 0

Fetch 0 0.00 0.00 0 0 0 0

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

total 2 0.00 0.00 0 1 0 0

Misses in library cache during parse: 1

Optimizer mode: ALL_ROWS

Parsing user id: 84 (recursive depth: 1)

Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation

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

0 0 0 TABLE ACCESS FULL T1 (cr=0 pr=0 pw=0 time=2 us cost=305 size=2484 card=12)

********************************************************************************

从上面使用了绑定变量的方法,可以看到,执行100次,只有一次硬解析。

而非绑定变量方法,每一次的SQL,都是独立解析及运行的。CPU的消耗也可以看到两者的差异。

1.4.绑定变量的SQL代码优化,主要是减少了SQL 的硬解析。

1.5 在OLTP 架构中,

1.5.1 SQL 简单而非常相似,并且结果集非常小,不同的只是谓语部分。所以这种情况下,执行计划都是一样的。

在执行计划都几乎不变的情况下。ORACLE使用变量来代替谓词,使用同一个执行计划,是非常合理的。

1.5.2 SQL 重复率很高,或者只是谓词条件不同而已;

1.5.3 SQL 语句执行条件多,条数越多,CPU的消耗就大,这种情况下,减少硬解析就越有意义了。

1.6 在OLAP 架构中

1.6.1 SQL 执行的重复率低,大部分都只是批量,定时加载,

1.6.2 数据聚合操作频繁;

1.6.3 SQL 语句执行条数少,SQL 硬解析对系统性能影响较小,更多的瓶颈是IO,

1.6.3 分区表的查询,相对也不太适合绑定变量技术.

综上所述,所以说OLAP不适合使用绑定变量。

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

2.用示例演示一次硬分析(hard parse)和一次软分析(soft parse),以及一次更软的分析(softer soft parse),并对给出演示结果。<br>

ORACLE SQL 执行过程:

数据库端收到一个sql 请求后,会建立一个进程,与用户进程组成一个会话,在pga区处理sql 请求。

然后开始访问sga的sharl pool,并解析SQL,生成执行计划;

如果一条SQL 在share pool中已经存在,那么ORACLE 只需奖已存在的执行计划应用到当前SQL上,去访问数据即可。这种情况称之为软解析(SOFT PARSE);

如果在共享汇中没有找到SQL的执行计划,ORACLE就会对SQL 进行: 语法解析,语义解析,生成执行计划等动作,这些解析步骤就总称为硬解析(HARD PARSE);

而这些解析步骤是比较消耗资源的。

还有另外一种解析是:缓存游标信息,后续的SQL不用再去打开一个新的cursor,而是直接去share pool 中找到已查询过的数据,这样就更省资源,

成为更软的解析(SOFTER SOFT PARSE).

2.1 演示数据准备及第一次执行效果

SQL> drop table t2 purge;

Table dropped.

SQL> create table t2 as select * from dba_objects;

Table created.

SQL> select count(0) from t2;

COUNT(0)

----------

76429

查询SQL 运行情况

SQL> select sql_text,parse_calls,loads,executions from v$sql where sql_text like 'select count(0) from t2' order by

SQL_TEXT PARSE_CALLS LOADS EXECUTIONS

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

select count(0) from t2 1 1 1

可以看到总解析 1次;硬解析 1次,执行次数 1 次;

下面我们再执行一次:

2.2 第二次执行效果

SQL> select count(0) from t2;

COUNT(0)

----------

76429

SQL> select sql_text,parse_calls,loads,executions from v$sql where sql_text like 'select count(0) from t2' order by

SQL_TEXT PARSE_CALLS LOADS EXECUTIONS

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

select count(0) from t2 2 1 2

这时可以看到总解析 2次;硬解析 1次,执行次数 2 次; 第2次没有进行硬解析,就是因为SQL 放在

SHARED_POOL中,进行了一次软解析;

2.3 我们再把SHARED_POOL清空,看看效果:

SQL> alter system flush shared_pool;

System altered.

SQL> select count(0) from t2;

COUNT(0)

----------

76429

SQL> select sql_text,parse_calls,loads,executions from v$sql where sql_text like 'select count(0) from t2' order by

SQL_TEXT PARSE_CALLS LOADS EXECUTIONS

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

select count(0) from t2 1 1 1

这时,ORACLE 认为是一条新的SQL了。所以又有一次硬解析。

2.4 softer_soft_parse 会话对游标的缓存

SQL> alter session set tracefile_identifier='tang';

Session altered.

SQL> alter system flush shared_pool;

System altered.

SQL> alter session set events '10046 trace name context forever,level 12';

Session altered.

SQL> alter session set sql_trace=true;

Session altered.

SQL>

SQL> show parameter session_cached_cursors;

NAME TYPE

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

VALUE

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

session_cached_cursors integer

50

SQL> set linesize 100;

SQL> select 'STAT-'||name,value from v$sysstat where name like '%parse%' or name like'%cursor%'

2 union all select 'LATCH-'||name,gets from v$latch where name = 'shared pool';

'STAT-'||NAME VALUE

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

STAT-opened cursors cumulative 10897

STAT-opened cursors current 28

STAT-pinned cursors current 12

STAT-session cursor cache hits 12908

STAT-session cursor cache count 882

STAT-cursor authentications 237

STAT-parse time cpu 91

STAT-parse time elapsed 224

STAT-parse count (total) 1752

STAT-parse count (hard) 1271

STAT-parse count (failures) 0

STAT-parse count (describe) 0

LATCH-shared pool 98158

13 rows selected.

SQL>

SQL> select count(0) from t10;

COUNT(0)

----------

76432

SQL> begin

2 for i in 1..10000 loop

3 execute immediate 'select count(0) from t10';

4 end loop;

5 end;

6 /

PL/SQL procedure successfully completed.

SQL> select substr('STAT-'||name,1,50) as name,value from v$sysstat where name like '%parse%' or name like'%cursor%' un

ets from v$latch where name = 'shared pool';

NAME VALUE

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

STAT-opened cursors cumulative 21492

STAT-opened cursors current 29

STAT-pinned cursors current 11

STAT-session cursor cache hits 23418

STAT-session cursor cache count 1033

STAT-cursor authentications 262

STAT-parse time cpu 96

STAT-parse time elapsed 230

STAT-parse count (total) 1887

STAT-parse count (hard) 1290

STAT-parse count (failures) 0

STAT-parse count (describe) 0

LATCH-shared pool 118288

13 rows selected.

SQL>

SQL> alter system flush shared_pool;

System altered.

SQL> alter session set session_cached_cursors=0;

Session altered.

SQL> select substr('STAT-'||name,1,50) as name,value from v$sysstat where name like '%parse%' or name like'%cursor%' union all

ets from v$latch where name = 'shared pool';

NAME VALUE

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

STAT-opened cursors cumulative 26250

STAT-opened cursors current 28

STAT-pinned cursors current 11

STAT-session cursor cache hits 28300

STAT-session cursor cache count 1671

STAT-cursor authentications 363

STAT-parse time cpu 148

STAT-parse time elapsed 300

STAT-parse count (total) 2855

STAT-parse count (hard) 1620

STAT-parse count (failures) 0

STAT-parse count (describe) 0

LATCH-shared pool 153871

13 rows selected.

SQL> select count(0) from t10;

COUNT(0)

----------

76432

SQL> begin

2 for i in 1..10000 loop

3 execute immediate 'select count(0) from t10';

4 end loop;

5 end;

6 /

PL/SQL procedure successfully completed.

SQL>

SQL> select substr('STAT-'||name,1,50) as name,value from v$sysstat where name like '%parse%' or name like'%cursor%' union all

ets from v$latch where name = 'shared pool';

NAME VALUE

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

STAT-opened cursors cumulative 39364

STAT-opened cursors current 30

STAT-pinned cursors current 10

STAT-session cursor cache hits 34321

STAT-session cursor cache count 1912

STAT-cursor authentications 442

STAT-parse time cpu 184

STAT-parse time elapsed 337

STAT-parse count (total) 13302

STAT-parse count (hard) 1814

STAT-parse count (failures) 0

STAT-parse count (describe) 0

LATCH-shared pool 177749

13 rows selected.

SQL>

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

3.用示例演示一次分析,多次执行的示例,并对给出演示结果。<br>

3.1 使用不绑定变量,执行3次不同的SQL,是各自进行硬分析的:

SQL> alter system flush shared_pool;

System altered.

SQL> select object_id from t10 where object_id=100;

OBJECT_ID

----------

100

SQL> select object_id from t10 where object_id=200;

OBJECT_ID

----------

200

SQL> select object_id from t10 where object_id=300;

OBJECT_ID

----------

300

SQL> select sql_text,parse_calls,loads,executions from v$sql where sql_text like 'select object_id from t10%'

SQL_TEXT PARSE_CALLS LOADS EXECUTIONS

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

select object_id from t10 where object_id=300 1 1 1

select object_id from t10 where object_id=200 1 1 1

select object_id from t10 where object_id=100 1 1 1

SQL>

3.2 使用绑定变量

SQL> var vid number;

SQL> execute :vid:=100;

PL/SQL procedure successfully completed.

SQL> select object_id from t10 where object_id:=vid;

select object_id from t10 where object_id:=vid

*

ERROR at line 1:

ORA-00920: invalid relational operator

SQL> select object_id from t10 where object_id=:vid;

OBJECT_ID

----------

100

SQL> execute :vid:=150;

PL/SQL procedure successfully completed.

SQL> select object_id from t10 where object_id=:vid;

OBJECT_ID

----------

150

SQL> execute :vid:=160;

PL/SQL procedure successfully completed.

SQL> select object_id from t10 where object_id=:vid;

OBJECT_ID

----------

160

SQL> select sql_text,parse_calls,loads,executions from v$sql where sql_text like 'select object_id from t10%';

SQL_TEXT PARSE_CALLS LOADS EXECUTIONS

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

select object_id from t10 where object_id=300 1 1 1

select object_id from t10 where object_id=200 1 1 1

select object_id from t10 where object_id=:vid 3 1 3

select object_id from t10 where object_id=100 1 1 1

SQL>

从上面最后的查询看到,最后一次使用变量的方式执行的3次SQL,只进行了一次硬分析

Oracle认为这3条SQL是完全一样的(除了谓词部分)所以第一次执行的时候做一次硬解析后续2条SQL只做软解析,比上一个少了2次硬解析,性能提高

绑定变量2

SQL> begin

2 for i in 1..3 loop

3 execute immediate 'select object_id from t10 where object_id=:i' using i;

4 end loop;

5 end;

6 /

PL/SQL procedure successfully completed.

SQL> select sql_text,parse_calls,loads,executions from v$sql where sql_text like 'select object_id from t10%';

SQL_TEXT PARSE_CALLS LOADS EXECUTIONS

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

select object_id from t10 where object_id=300 1 1 1

select object_id from t10 where object_id=200 1 1 1

select object_id from t10 where object_id=:i 1 1 3

select object_id from t10 where object_id=:vid 3 1 3

select object_id from t10 where object_id=100 1 1 1

SQL>

Oracle认为这3条SQL是完全一样的(除了谓词部分),和上面不同的是只做了1次硬解析没有软解析,反复执行了3次。

我们做了一个循环,用leo变量代替谓词常量,每次都用相同的执行计划(执行计划不需要重新生成),只是改变一下常量值而已。

上面3种执行方法,从上面的查询中,很好的看出各自的不同,优点最明显的就是最后一次的SQL.

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

4.演示一个父游标产生3个子游标的示例,并分别说明每个子游标产生的原因。<br>

4.1 把用户TANG.10 的查询权限赋给 test,scott;

SQL> grant select on t10 to test;

Grant succeeded

SQL> grant select on t10 to scott;

Grant succeeded

SQL>

4.2 在test,scott 用户下各建立T10表;

C:\Users\Administrator>sqlplus test/test@orcl

SQL*Plus: Release 11.2.0.1.0 Production on Fri Dec 6 17:27:31 2013

Copyright (c) 1982, 2010, Oracle. All rights reserved.

Connected to:

Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> create table t10 as select * from tang.t10;

Table created.

SQL> select count(1) from t10;

COUNT(1)

----------

76430

SQL>

C:\Users\Administrator>sqlplus scott/scott@orcl

SQL*Plus: Release 11.2.0.1.0 Production on Fri Dec 6 17:30:24 2013

Copyright (c) 1982, 2010, Oracle. All rights reserved.

Connected to:

Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> create table t10 as select * from tang.t10;

Table created.

SQL> select count(1) from t10;

COUNT(1)

----------

76430

SQL>

4.3 在用用户tang 查询表

SQL> select count(1) from t10;

COUNT(1)

----------

76430

4.4 查询子游标记录

SQL>select sql_id,child_number,sql_text,parse_calls,plan_hash_value,loads from v$sql

where sql_text='select count(1) from t10';

SQL_ID CHILD_NUMBER SQL_TEXT PARSE_CALLS PLAN_HASH_VALUE LOADS

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

1 9z6r9gcz6gnmz 0 select count(1) from t10 3 1331550546 1

2 9z6r9gcz6gnmz 1 select count(1) from t10 2 1331550546 1

3 9z6r9gcz6gnmz 2 select count(1) from t10 2 1331550546 1

SQL_ID 相同,即说明是使用了同一个父游标,用子游标来区分不同属性的相同SQL

CHILD_NUMBER:这个字段不同,说明oracle知道这是3个用户下的相同SQL语句

LOADS:都做了1次硬解析,说明oracle知道这是3个不完全相同的SQL语句

select sql_id,child_number,child_address,sql_text

from v$sql where sql_text='select count(1) from t10';

SQL_ID CHILD_NUMBER CHILD_ADDRESS SQL_TEXT

1 9z6r9gcz6gnmz 0 00000002AF6653C0 select count(1) from t10

2 9z6r9gcz6gnmz 1 00000002AF778630 select count(1) from t10

3 9z6r9gcz6gnmz 2 00000002AFD6C328 select count(1) from t10

CHILD_ADDRESS 值不相同,即3个子游标的不同入口地址。

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

5.演示ACS(adaptiver cursor sharing)的效果。<br>

5.1 建立测试环境数据

SQL> drop table t purge;

Table dropped.

SQL> create table t as select case when rownum<=100 then 1 else 2 end as id from dual connect by rownum<1000000;

Table created.

SQL> create index idx_t_id on t(id);

Index created.

5.2 对表进行统计分析(ACS 要有直方图信息)

SQL> execute dbms_stats.gather_table_stats(user,'T',method_opt=>'for all columns size 2');

PL/SQL procedure successfully completed.

SQL> set autotrace off;

SQL> select id,count(0) from t group by id;

ID COUNT(0)

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

1 100

2 999899

SQL> set autot trace exp;

SQL> select count(0) from t where id=1;

Execution Plan

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

Plan hash value: 1700799834

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

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

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

| 0 | SELECT STATEMENT | | 1 | 3 | 3 (0)| 00:00:01 |

| 1 | SORT AGGREGATE | | 1 | 3 | | |

|* 2 | INDEX RANGE SCAN| IDX_T_ID | 181 | 543 | 3 (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

2 - access("ID"=1)

SQL> select count(0) from t where id=2;

Execution Plan

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

Plan hash value: 2966233522

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

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

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

| 0 | SELECT STATEMENT | | 1 | 3 | 433 (3)| 00:00:06 |

| 1 | SORT AGGREGATE | | 1 | 3 | | |

|* 2 | TABLE ACCESS FULL| T | 999K| 2928K| 433 (3)| 00:00:06 |

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

Predicate Information (identified by operation id):

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

2 - filter("ID"=2)

SQL>

从上面两个执行计划可以看出,两个执行计划使用了ACS,走了不同的执行计划;

5.3 使用绑定变量执行SQL,并查看不同变量时的变化

SQL> alter session set sql_trace=true;

Session altered.

SQL> alter session set tracefile_identifier='tang'

2 ;

Session altered.

SQL> var v_num number;

SQL> execute :v_num:=2;

PL/SQL procedure successfully completed.

SQL> select count(0) from t where id=:v_num;

COUNT(0)

----------

999899

SQL> execute :v_num:=1;

PL/SQL procedure successfully completed.

SQL> select count(0) from t where id=:v_num;

COUNT(0)

----------

100

SQL> select count(0) from t where id=:v_num;

COUNT(0)

----------

100

SQL> alter session set sql_trace=false;

Session altered.

SQL> select value from v$diag_info where name='Default Trace File';

VALUE

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

D:\APP\ORACLE\diag\rdbms\orcl\orcl\trace\orcl_ora_5952_tang.trc

SQL>

跟踪文件如下:

5.3.1 定义变量为2 时的执行计划:

SQL ID: 9qvxqz87xn8vt Plan Hash: 0

BEGIN :v_num:=2; END;

call count cpu elapsed disk query current rows

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

Parse 1 0.00 0.00 0 0 0 0

Execute 1 0.00 0.00 0 0 0 1

Fetch 0 0.00 0.00 0 0 0 0

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

total 2 0.00 0.00 0 0 0 1

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: 84

********************************************************************************

--执行绑定变量SQL,我们可以看执行计划为全表扫描,这是没有问题的,因为数据比较倾斜,

id为2的记录很多,之前的测试也是全表扫描

--但是我们要注意,这个SQL语句执行了2次,也就是全表扫描的方式执行了2次,

也就是当值为1的第一次执行走的是全表扫描。

5.3.2 定义变量为1 时, 已重新进行了一个硬分析。走的也是全表扫描,这点和想象的不一样。

感觉很奇怪,

SQL ID: fdp2j9cdw8pc5 Plan Hash: 0

BEGIN :v_num:=1; END;

call count cpu elapsed disk query current rows

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

Parse 1 0.00 0.00 0 0 0 0

Execute 1 0.00 0.00 0 0 0 1

Fetch 0 0.00 0.00 0 0 0 0

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

total 2 0.00 0.00 0 0 0 1

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: 84

********************************************************************************

再看一下是否有错:

从下面的测试中看到,不管我使用变量 1或者2 ,走的都是全表扫描。并没有走索引。

查看 is_bind_sensitive

表示游标是否对绑定变量敏感。数值如果为Y,表示当绑定变量的数值发生变化后,

优化器有可能会产生一个不同的执行计划,简单说就是ACS生效了。

我这里就是因为这个,一直是N,如下:

SQL> select sql_id,child_number,executions,loads,buffer_gets,is_bind_sensitive,is_bind_aware from v$sql where sql_text like 'select count(0) from t where id=:v_n';

SQL_ID CHILD_NUMBER EXECUTIONS LOADS

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

BUFFER_GETS bin bin bin

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

3fvuhx84ba43x 0 0 1

0 N N Y

SQL> exec :n :=2;

PL/SQL procedure successfully completed.

SQL> select count(*) from t where id=:n;

COUNT(*)

----------

999899

SQL> select sql_id,child_number,executions,loads,buffer_gets,is_bind_sensitive as "bind_sensi",is_bind_aware as "

re" from v$sql where sql_text like 'select count(*) from t where id=:n';

SQL_ID CHILD_NUMBER EXECUTIONS LOADS

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

BUFFER_GETS bin bin bin

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

3fvuhx84ba43x 0 1 1

1527 N N Y

SQL> exec :n :=2;

PL/SQL procedure successfully completed.

SQL> select count(*) from t where id=:n;

COUNT(*)

----------

999899

SQL> select sql_id,child_number,executions,loads,buffer_gets,is_bind_sensitive as "bind_sensi",is_bind_aware as "

re" from v$sql where sql_text like 'select count(*) from t where id=:n';

SQL_ID CHILD_NUMBER EXECUTIONS LOADS

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

BUFFER_GETS bin bin bin

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

3fvuhx84ba43x 0 2 1

3054 N N Y

SQL>

SQL> exec :n :=1;

PL/SQL procedure successfully completed.

SQL> select count(*) from t where id=:n;

COUNT(*)

----------

100

SQL> select sql_id,child_number,executions,loads,buffer_gets,is_bind_sensitive as "bind_sensi",is_bind_aware as "

re" from v$sql where sql_text like 'select count(*) from t where id=:n';

SQL_ID CHILD_NUMBER EXECUTIONS LOADS

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

BUFFER_GETS bin bin bin

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

3fvuhx84ba43x 0 3 1

4581 N N Y

SQL>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐