设为首页 加入收藏

TOP

一张6亿条数据表引发的事故(三)
2015-11-21 03:26:35 来源: 作者: 【 】 浏览:95
Tags:一张 6亿 数据 引发 事故
--------------------- 4 - access("C"."COLLECT_ID"=TO_NUMBER(:COLLECT_ID)) 5 - access("D"."MODEL_ID"="C"."MODEL_ID" AND "D"."DATA_DATE"=:DATA_DATE AND "D"."DATA_TYPE"=:DATA_TYPE AND "D"."VALUE_FLAG"=0) 19 rows selected.
发现走了索引,但是当时为什么没有走索引呢。并且在二节点走了全表扫描,一节点走的是索引范围扫描。


该oracle数据库的版本为10.2.0.5,在11g之前没有引入ACS(Adaptive Cursor Sharing),所以这里CBO在第一次进行硬解析的时候才会窥视变量的值,并且生成执行计划,之后一直使用相同的执行计划。
这里我猜想,在2节点。第一次使用绑定变量的时候,CBO认为应该使用全表扫描效率更高,所以在以后一直使用该执行计划。然而在一节点,第一次使用绑定变量的时候,CBO认为走范围扫描效率更高。所以这里导致1节点和2节点的执行计划不一样。




找到原因了,就好办了。业务人员怕数据库负载过大导致宕机,遂叫我把该sql的相关进程(发现30个进程)全部kill掉。kill完进程后磁盘IO瞬间降到50MB。


还没有完,改sql以后还会有这种选择。我们怎么去避免?
既然了解了CBO的做法,那就触发它再一次去执行一次硬解析获得正确的执行计划。有如下4种方法:
1、alter system flush shared_pool(想跪就跑这个)
2、对相关表做DDL操作
3、重新收集统计信息
4、dbms_shared_pool.purge


前面三种方案对生产 系统都影响比较大,所以利用第四种方法。

?

?

SQL> select address,hash_value,executionsfrom v$sql where hash_value=54043712
 
ADDRESS          HASH_VALUE EXECUTIONS
 
---------------- ---------- ---------- -----------
0000040229F039E0 54043712          1           

SQL> alter session set events '5614566 trace name context forever';

SQL> exec dbms_shared_pool.purge('0000040229F039E0,54043712','C');
重新利用合适的绑定变量跑出正确的执行计划即可。


如何永久保持不变呢?
加hint,强制走索引。

?

?

explain plan for SELECT /*+ index(zbdba1,IDX_C_COLLECT_MD_001)* / D.MODEL_ID,
       D.OBJ_ID,
       D.OBJ_TYPE,
       D.DATA_TYPE,
       D.DATA_DATE,
       D.DATA_FROM_DATE,
       D.DATA_TO_DATE,
       D.DATA_FLAG
  FROM EIC2.zbdba1 D, EIC2.zbdba2 C
WHERE D.MODEL_ID = C.MODEL_ID
   AND C.COLLECT_ID = '70350'
   AND D.DATA_DATE = to_date('06/01/15','MM/DD/YY')
   AND D.DATA_TYPE = '02'
   AND D.VALUE_FLAG = 0;

如果以后该索引有变化,也将会失效。

?


当然优化没有一劳永逸的事情,针对大小超过50GB,数据量高达6亿条的表还是要定期检查它相关sql的执行计划。
?


首页 上一页 1 2 3 下一页 尾页 3/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Oracle分区表的层次查询如何才能.. 下一篇使用11gDNFS建立基于DNFS的tables..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: