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. 当有人告诉你,“没有任何差别啊、所有的步骤都是一模一样的啊”,不要相信。问题的产生一定有原因。

Issues about oracle bin file s bit not set

很早之前记录过一个问题 – oracle可执行文件s位导致的Cluster资源组无法正常启动的问题解决

今天在另外一个客户处又出现了同样的问题,解决方法一样,但是问题现象却不一样,着实折腾了很久。问题现象是,启动数据库没有任何报错,启动监听也没有任何问题,lsnrctl services命令显示一切正常,但是在远程客户端通过监听登陆数据库,第一次会报Oracle not available的错误,之后再次尝试会报TNS-12516错误, “TNS:listener could not find instance with matching protocol stack”,此时再次检查lsnrctl services,会发现监听的状态变为blocked。

同样是使用tar包安装的Oracle9i软件,同样是在Solaris 9中,似乎这是Solaris系统中tar命令的一个毛病。

最后执行chmod解决问题。

chmod u+s,g+s $ORACLE_HOME/bin/oracle