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

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

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi


创建测试脚本
引用
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;
/

将cursor_sharing参数改为similar,可以看出谓词连接采用>(还有>, <, >=, <=, LIKE)时,SQL在共享parent cursor时不能共享child cursor
引用
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


将谓词连接改为=时,SQL在共享parent cursor时能共享child cursor
引用
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


将cursor_sharing参数改为force,我们看到cursor实现了共享。
引用
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

进一步将cursor_sharing改为exact,cursor甚至不能在parent级别实现共享
引用
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

二、cursor_sharing参数histogram与SQL version count

在table t1所有列上收集直方图(J列除外)
引用
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


将cursor_sharing改为similar,发现在有直方图的列上不能实现child cursor共享。
引用
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


将cursor_sharing改为force时,无论在有直方图或无直方图的列上都实现了游标共享。
引用
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

将cursor_sharing改为exact,并使用绑定变量,经测试实现了游标共享,但是需要注意的是如果使用绑定变量由于BIND PEEKING,会导致执行计划不稳定
引用
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

你可能感兴趣的:(oracle,sql,J#)