Execution Plan!

今天客户做系统升级,从原先的Oracle 8.1.7.4升级为Oracle 9.2.0.8 RAC,并且将应用系统从1.1版本升级为2.0版本,是一个很大的举动。

其中牵涉到数据转换,软件开发商用简单的insert into xxx select … from yyy@dblink a, zzz b where a.ccc=b.ccc这样的语句完成数据转换,之前已经在测试环境中多次运行过,但是今天却仍然发生了问题,本来在测试环境中只需要运行100秒的转换过程在生产环境中运行了将近1个小时也没有结束,因为转换过程是大量顺序执行的insert语句,因此其中一个语句堵塞了,下面的语句也无法运行。

包括客户、软件开发商在内的十数人站在身后,为什么测试环境中运行如此快的SQL在产品环境中变得如此缓慢?该如何解决?如果在已经严格计算过的时间窗口内无法解决,是否需要回退整个升级工作?情况看上去很紧急。

因为牵涉到dblink,因此检查网络,没有发现问题。

让软件开发商在测试环境中重新跑这个SQL,速度仍然很快,检查执行计划,发现在测试环境中是Full table scan + Hash Join,而生产环境中却是Index range scan + Merge Join,检查互相Join的表,一个只有几千条记录,一个有几十万,很明显Hash Join应该是明智的选择。

没有时间去检查为什么产品环境中Oracle选择了更差的执行计划,加Hint先去解决问题。

添加了/*+USE_HASH(C,B) ORDERED*/提示,重新检查执行计划,已经是想要的Hash Join了,再次执行SQL,40多秒就完成了数据转换。

不同的执行计划差异就是如此之大,CBO任重道远。

Update@2008-6-20

今天主要任务是检查为什么相同SQL的执行计划在不同的机器上会不一样。通过10053 trace看到的区别。

生产环境中:
***********************
Table stats Table: XXX Alias: D
TOTAL :: CDN: 0 NBLKS: 1 AVG_ROW_LEN: 0

测试环境中:
***********************
Table stats Table: XXX Alias: D
TOTAL :: (NOT ANALYZED) CDN: 2893269 NBLKS: 35422 AVG_ROW_LEN: 100

很明显,生产环境中认为这张表是0条记录,但是在测试环境中因为没有做过表分析,Oracle选择了2893269条记录作为猜测值。这就是导致执行计划差异巨大的真正原因。

询问软件开发商的工程师,确实之前的多次测试中,在数据转换之前都没有做表分析,而这次生产环境却做了表分析,XXX表中的数据是在数据转换过程中才插入的,而数据转换之前做的表分析则告诉Oracle这张表中没有数据(实际上却有超过120万条记录)。

这次的故障告诉我们:
1. 表分析不要随便做,做错了比不做还差。
2. 当有人告诉你,“没有任何差别啊、所有的步骤都是一模一样的啊”,不要相信。问题的产生一定有原因。

5 thoughts on “Execution Plan!

  1. dba says:

    为什么不直接到10g RAC?
    是不是Oracle打算以后再帮这个客户升级一次,多骗一点啊? 🙂

  2. Big Aquarium says:

    包括客户、软件开发商在内的十数人站在身后。。。

    原来压力这么大呢 。。。:X

  3. 棉花糖ONE says:

    统计信息不对,走错了执行计划为什么不收集统计信息,加了hint这语句解决了,那别的语句查这个表的时候,基本都走全表了,如果测试环境没有统计信息那怎么会评估出2893269,只能说测试库的统计信息比较准确,所以oracle走了正确的执行计划

Leave a Reply

Your email address will not be published. Required fields are marked *