• 关于游标共享测试和总结


    游标共享分父游标共享和子游标共享。

    首先看一下父游标共享,父游标共享的前提条件是sql文本要完全相同。

    如下sql语句中

    s1: select * from t1 where object_id=4;

    s2: select * from T1 where object_id=4;

    s3 :select * from t1 where object_id=4;

    s4: select * from  t1 where object_id=4;

    s2的表名(t1)大写与s1的表名(t1)小写不能算作同一个语句,s4 中t1 之前有空格,所以与其它语句也不会相同,s1和s3完全一样,所以它们是同一条语句。

    创建测试表

    SQL>create table t1 as select * from    dba_objects;
    SQL>create index idx_t1 on t1(object_id);
    SQL> select count(*) from t1;
    
      COUNT(*)
    ----------
         91044

    注:oracle  在sql硬解析之前首先会将对sql语句生成散列值,进而在库缓存中去搜索,如果能找到,则说明语句之前有执行过,这时语句有一个可共享的父游标。

    执行上述4条语句,然后查询v$sqlarea

    select sql_id,sql_text,executions from v$sqlarea where sql_text like  '%=4';

    SQL_ID	      SQL_TEXT												   EXECUTIONS
    ------------- ---------------------------------------------------------------------------------------------------- ----------
    0msd0jqtz1fta select * from t1 where object_id=4									    2
    cq9uku9a36w3j select * from  t1 where object_id=4									    2
    b472gkg0mgbzv  select * from T1 where object_id=4									    1
    

    由此可证明由于语句大大小写以及空格等原因,生成了了三个父游标。  

    子游标能够共享的前提是优化器环境,用户模式等需要完全一致

    下面以不同的优化器模式执行s1 

    SQL> alter session set optimizer_mode = all_rows;
    
    Session altered.
    
    SQL> select * from t1 where object_id=4;
    结果略
    SQL> alter session set optimizer_mode = first_rows;
    
    Session altered.
    
    SQL> select * from t1 where object_id=4;
    结果略
    

    查询v$sql 视图

    SQL> select sql_id,child_number,optimizer_mode,plan_hash_value from v$sql where sql_text='select * from t1 where object_id=4';
    
    SQL_ID	      CHILD_NUMBER OPTIMIZER_ PLAN_HASH_VALUE
    ------------- ------------ ---------- ---------------
    0msd0jqtz1fta		 0 ALL_ROWS	   3983389365
    0msd0jqtz1fta		 1 FIRST_ROWS	   3983389365
    

    可以看到同父游标(sql_id相同)下有两个子游标,优化器环境不同导致优化器生成两个子游标,PLAN_HASH_VALUE这一列相同说明两个子游标共享相同的执行计划。

    注:是否生成子游标取决与oracle的两个检查,一个是语义,另一个是优化器环境检查。所谓语义检查,例如如果用户 u1 和 u2 下都有 t1 这个表,u1 和 u2 都提交了 上述的sql即使sql文本完全一样,优化器也会意识到这个t1 表是存在两个用户下完全不相同的两个表,结果就是会为两个用户分别生成一个子游标。所谓优化器环境,例如一些以optimizer_开头的初始化参数如optimizer_adaptive_features  ,optimizer_mode 不同都会造成产生子游标。

     在v$sql_shared_cursor 视图中可以看到更具体的原因。

    SQL> select sql_id,optimizer_mode_mismatch,child_number,to_char(reason) reason  from v$sql_shared_cursor where sql_id='0msd0jqtz1fta';
    
    SQL_ID	      O CHILD_NUMBER REASON
    ------------- - ------------ ----------------------------------------------------------------------------------------------------
    0msd0jqtz1fta N 	   0 <ChildNode><ChildNumber>0</ChildNumber><ID>3</ID><reason>Optimizer mismatch(10)</reason><size>3x4</s
    			     ize><optimizer_mode_hinted_cursor>0</optimizer_mode_hinted_cursor><optimizer_mode_cursor>1</optimize
    			     r_mode_cursor><optimizer_mode_current>2</optimizer_mode_current></ChildNode>
    
    0msd0jqtz1fta Y 	   1
    

      

  • 相关阅读:
    论球迷和程序员
    山哥,你是怎么提高设计能力的?
    一个想休息的线程:JVM到底是怎么处理锁的?怎么不让我阻塞呢?
    由“面经”引发的思考
    99%的创业公司都不值得加入
    大牛是怎么炼成的?
    RMQ问题 与众不同 尚未攻克
    YbtOj例题:二叉堆3 龙珠游戏
    离散化模板
    YbtOJ练习:广搜 3 追捕小狗
  • 原文地址:https://www.cnblogs.com/wangxingc/p/5618380.html
Copyright © 2020-2023  润新知