ITPub博客

首页 > 数据库 > Oracle > [20210201]19c计算标量子查询缓存数量.txt

[20210201]19c计算标量子查询缓存数量.txt

原创 Oracle 作者:lfree 时间:2021-02-01 10:13:52 1 删除 编辑

[20210201]19c计算标量子查询缓存数量.txt

--//测试19C下标量子查询缓存数量的数量,以前在10g,11g,12c下测试过。

1.环境:
> @ prxx
==============================
PORT_STRING                   : x86_64/Linux 2.4.xx
VERSION                       : 19.0.0.0.0
BANNER                        : Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
BANNER_FULL                   : Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.9.0.0.0
BANNER_LEGACY                 : Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
CON_ID                        : 0
PL/SQL procedure successfully completed.

> @ hide  _query_execution_cache_max_size
NAME                            DESCRIPTION                       DEFAULT_VALUE SESSION_VALUE SYSTEM_VALUE ISSES ISSYS_MOD
------------------------------- --------------------------------- ------------- ------------- ------------ ----- ---------
_query_execution_cache_max_size max size of query execution cache TRUE          131072        131072       TRUE  DEFERRED
-//该参数与11g一致,估计hash table size没有变化.

2.建立测试脚本:
--//脚本scalar_sub_03.sql来源Jonathan Lewis的<基于成本的Oracle优化法则>,我做了少量改写,使用
--//dbms_application_info.set_client_info设置函数调用次数。
--//另外我想测试如果输入参数是字符,输出参数是number,会出现什么情况。主要想探究hash table保存一些什么。

create table t1 tablespace users
as
with generator as (
    select  --+ materialize
        rownum  id
    from    all_objects
    where   rownum <= 3000
)
select
    /*+ ordered use_nl(v2) */
    rownum          n1,
    lpad(rownum,16,'0') v16,
    lpad(rownum,32,'0') v32
from
    generator   v1,
    generator   v2
where
    rownum <= 16384
;

insert /*+ append */ into t1 select * from t1;
commit;

begin
    dbms_stats.gather_table_stats(
        user,
        't1',
        cascade => true,
        estimate_percent => null,
        method_opt => 'for all columns size 1'
    );
end;
/

create or replace package pack1 as
    g_ct    number(10) := 0;
    function f_n(i in number)   return number;
    function f_v(i in varchar2) return varchar2;
    function f_vn(i in varchar2) return number;
end;
/

create or replace package body pack1 as
function f_n(i in number)   return number
is
begin
    dbms_application_info.set_client_info(userenv('client_info')+1 );
    return i;
end;

function f_v(i in varchar2) return varchar2
is
begin
    dbms_application_info.set_client_info(userenv('client_info')+1 );
    return i;
end
;


function f_vn(i in varchar2) return number
is
begin
    dbms_application_info.set_client_info(userenv('client_info')+1 );
    return length(i);
end
;
end;
/

3.测试1:

exec  dbms_application_info.set_client_info(0);
select count(distinct x) from  ( select  /*+ no_merge */ (select pack1.f_n(n1) from dual) x from t1) ;
select 16384*2 - userenv('client_info') hash_table_size from dual;

--//简单介绍原理,利用执行的sql语句循环执行2遍,从1到16384,形成一个hash table并且填满,注意执行次数一定要充足。
--//第1遍扫描形成hash table,如果冲突dbms_application_info.set_client_info(userenv('client_info')+1 );,但是该值对应的返
--//回不会进入hash table。
--//第2遍扫描,如果函数返回存在hash table ,不会真正调用函数。
--//如果函数返回不存在hash table(也就是出现冲突),一定会调用函数,并且
--//dbms_application_info.set_client_info(userenv('client_info')+1 ).
--//这样2 * 16384 - userenv('client_info')  就是Hash table的大小。
--//注意第一遍扫描的执行次数(这里是16384)一定要填满hash table才行,否则计算错误。

> HASH_TABLE_SIZE
---------------
           1024
--//HASH_TABLE_SIZE=1024

4.测试2:
--//看看字符串的情况.
exec  dbms_application_info.set_client_info(0);
select count(distinct x) from ( select  /*+ no_merge */ (select pack1.f_v(v16) from dual) x from t1) ;
select 16384*2 - userenv('client_info') hash_table_size from dual;

> HASH_TABLE_SIZE
---------------
             32
--//HASH_TABLE_SIZE=32            

--//继续测试使用v32的情况:
exec  dbms_application_info.set_client_info(0);
select count(distinct x) from ( select  /*+ no_merge */ (select pack1.f_v(v32) from dual) x from t1) ;
select 16384*2 - userenv('client_info') hash_table_size from dual;

> select 16384*2 - userenv('client_info') hash_table_size from dual;
HASH_TABLE_SIZE
---------------
             32
--//HASH_TABLE_SIZE=32            
--//函数f_v的返回没有长度限制的字符串,相当于4000个字符.导致两个测试hash table szie=32。

--//限制字符的返回量仅仅80个字符看看.
exec dbms_application_info.set_client_info(0);
select count(distinct x) from ( select  /*+ no_merge */ (select substr(pack1.f_v(v32),1,80) from dual) x from t1) ;
select 16384*2 - userenv('client_info') hash_table_size from dual;

> HASH_TABLE_SIZE
---------------
            512


--//改用f_vn函数看看,这个以前没有测试:
exec  dbms_application_info.set_client_info(0);
select count(distinct x) from ( select  /*+ no_merge */ (select pack1.f_vn(v32) from dual) x from t1) ;
select 16384*2 - userenv('client_info') hash_table_size from dual;
> HASH_TABLE_SIZE
---------------
           1024
--//视乎这个hash_table仅仅保存结果.不然不会出现返回number,可以保存1024的情况.

5.也就是适当增加_query_execution_cache_max_size可以避免hash冲突,增加hash table size大小.

SCOTT@test01p> alter session set "_query_execution_cache_max_size"=262144;
Session altered.

--//注意测试前增加样本的大小2*16384条记录,便于第一遍扫描填满hash table。
--//drop table t1 purge;
create table t1
as
with generator as (
    select  --+ materialize
        rownum  id
    from    all_objects
    where   rownum <= 3000
)
select
    /*+ ordered use_nl(v2) */
    rownum          n1,
    lpad(rownum,16,'0') v16,
    lpad(rownum,32,'0') v32
from
    generator   v1,
    generator   v2
where
    rownum <= 16384*2
;

insert /*+ append */ into t1 select * from t1;
commit;

--//重复前面的测试。
exec  dbms_application_info.set_client_info(0);
select count(distinct x) from  ( select  /*+ no_merge */ (select pack1.f_n(n1) from dual) x from t1) ;
select 16384*4 - userenv('client_info') hash_table_size from dual;

> HASH_TABLE_SIZE
---------------
           2048


exec  dbms_application_info.set_client_info(0);
select count(distinct x) from ( select  /*+ no_merge */ (select pack1.f_v(v16) from dual) x from t1) ;
select 16384*4 - userenv('client_info') hash_table_size from dual;

> HASH_TABLE_SIZE
---------------
             64

6.总结:
--//返回数字,19c缺省hash table size=1024.
--//受隐含参数_query_execution_cache_max_size限制,19c缺省131072.字符串hash table size最大1024,最小32.
--//增加_query_execution_cache_max_size可以避免hash冲突,增加hash table size大小.

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/267265/viewspace-2754952/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
熟悉oracle相关技术,擅长sql优化,rman备份与恢复,熟悉linux shell编程。

注册时间:2008-01-03

  • 博文量
    4006
  • 访问量
    7969544