Oracle cursor_sharing,histogram对于sql version count的影响

本文章主要研究cursor_sharing参数不同设置,histograms收集与否对SQL version count 产生的影响。
一、cursor_sharing参数与SQL version count
数据库研究版本:
[quote]SQL> select * from v$version where rownum<2;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi[/quote]

创建测试脚本
[quote]create table t1( i number, j number, k number);
begin
for i in 1..10000 loop
insert into t1 values( i, i, i);
end loop;
end;
/[/quote]
将cursor_sharing参数改为similar,可以看出谓词连接采用>(还有>, <, >=, <=, LIKE)时,SQL在共享parent cursor时不能共享child cursor
[quote]SQL> alter session set cursor_sharing=similar
2 ;

Session altered.

SQL> select count(*) from t1 where i > 10;

COUNT(*)
----------
9990

SQL>select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i > :"SYS_B_0"
1


SQL> select count(*) from t1 where i > 20;

COUNT(*)
----------
9980

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i > :"SYS_B_0"
2


SQL> select count(*) from t1 where i > 30;

COUNT(*)
----------
9970

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i > :"SYS_B_0"
3[/quote]

将谓词连接改为=时,SQL在共享parent cursor时能共享child cursor
[quote]SQL> select count(*) from t1 where i=100;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i > :"SYS_B_0"
3

select count(*) from t1 where i=:"SYS_B_0"
1

SQL> select count(*) from t1 where i=200;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i > :"SYS_B_0"
3

select count(*) from t1 where i=:"SYS_B_0"
1[/quote]

将cursor_sharing参数改为force,我们看到cursor实现了共享。
[quote]SQL> alter session set cursor_sharing=force;

Session altered.

SQL> select count(*) from t1 where i > 40;

COUNT(*)
----------
9960

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i > :"SYS_B_0"
4

select count(*) from t1 where i=:"SYS_B_0"
1

SQL> select count(*) from t1 where i > 50;

COUNT(*)
----------
9950

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i > :"SYS_B_0"
4

select count(*) from t1 where i=:"SYS_B_0"
1[/quote]
进一步将cursor_sharing改为exact,cursor甚至不能在parent级别实现共享
[quote]SQL> alter session set cursor_sharing=exact;

Session altered.

SQL> select count(*) from t1 where i > 70;

COUNT(*)
----------
9930

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i > :"SYS_B_0"
4

select count(*) from t1 where i >:"SYS_B_0"
1

select count(*) from t1 where i=:"SYS_B_0"
1


SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i > 70
1


SQL> select count(*) from t1 where i > 80;

COUNT(*)
----------
9920

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i > :"SYS_B_0"
4

select count(*) from t1 where i >:"SYS_B_0"
1

select count(*) from t1 where i=:"SYS_B_0"
1


SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i > 80
1

select count(*) from t1 where i > 70
1
[/quote]
二、cursor_sharing参数histogram与SQL version count

在table t1所有列上收集直方图(J列除外)
[quote]SQL> exec DBMS_STATS.GATHER_TABLE_STATS(ownname=>'sys',tabname=>'t1',method_opt=>'FOR ALL COLUMNS SIZE 10');

PL/SQL procedure successfully completed.

SQL> exec DBMS_STATS.GATHER_TABLE_STATS(ownname=>'sys',tabname=>'t1',method_opt=>'FOR COLUMNS J SIZE 1');

PL/SQL procedure successfully completed.

SQL> select COLUMN_NAME,NUM_BUCKETS,HISTOGRAM from dba_tab_columns where OWNER='SYS' and TABLE_NAME='T1';

COLUMN_NAME NUM_BUCKETS HISTOGRAM
------------------------------ ----------- ---------------
I 10 HEIGHT BALANCED
J 1 NONE
K 10 HEIGHT BALANCED[/quote]

将cursor_sharing改为similar,发现在有直方图的列上不能实现child cursor共享。
[quote]SQL> alter session set cursor_sharing = similar;

Session altered.

SQL> select count(*) from t1 where i = 10;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :"SYS_B_0"
1


SQL> select count(*) from t1 where i = 20;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :"SYS_B_0"
2


SQL> select count(*) from t1 where i = 30;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :"SYS_B_0"
3


SQL> alter system flush shared_pool;

System altered.

SQL> select count(*) from t1 where j = 10;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where j = :"SYS_B_0"
1


SQL> select count(*) from t1 where j = 20;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where j = :"SYS_B_0"
1


SQL> select count(*) from t1 where j = 30;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where j = :"SYS_B_0"
1[/quote]

将cursor_sharing改为force时,无论在有直方图或无直方图的列上都实现了游标共享。
[quote]SQL> alter system flush shared_pool;

System altered.

SQL> alter session set cursor_sharing=force;

Session altered.

SQL> select count(*) from t1 where i = 10;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :"SYS_B_0"
1


SQL> select count(*) from t1 where i = 20;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :"SYS_B_0"
1


SQL> select count(*) from t1 where i = 30;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :"SYS_B_0"
1

SQL> select count(*) from t1 where j = 10;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :"SYS_B_0"
1

select count(*) from t1 where i = :"SYS_B_0"
1


SQL> select count(*) from t1 where j = 20;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :"SYS_B_0"
1

select count(*) from t1 where i = :"SYS_B_0"
1


SQL> select count(*) from t1 where j = 30;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :"SYS_B_0"
1

select count(*) from t1 where i = :"SYS_B_0"
1[/quote]
将cursor_sharing改为exact,并使用绑定变量,经测试实现了游标共享,但是需要注意的是如果使用绑定变量由于BIND PEEKING,会导致执行计划不稳定
[quote]SQL> alter system flush shared_pool;

System altered.

SQL> alter session set cursor_sharing=exact;

Session altered.

SQL> variable i number;
SQL> exec :i:=10

PL/SQL procedure successfully completed.

SQL> select count(*) from t1 where i = :i;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :i
1


SQL> exec :i:=20

PL/SQL procedure successfully completed.

SQL> select count(*) from t1 where i = :i;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :i
1


SQL> exec :i:=0

PL/SQL procedure successfully completed.

SQL> select count(*) from t1 where i = :i;

COUNT(*)
----------
0

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :i
1

SQL> variable j number;
SQL> exec :j:=10

PL/SQL procedure successfully completed.

SQL> select count(*) from t1 where j = :j;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where i = :i
1


SQL> exec :j:=100

PL/SQL procedure successfully completed.

SQL> select count(*) from t1 where j = :j;

COUNT(*)
----------
1

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where j = :j
1

select count(*) from t1 where i = :i
1


SQL> exec :j:=1000

PL/SQL procedure successfully completed.

SQL> select sql_text,version_count from v$sqlarea where
2 sql_text like 'select count(*) from t1 where%';

SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT
-------------
select count(*) from t1 where j = :j
1

select count(*) from t1 where i = :i
1
[/quote]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值