我们在生产中有一个独特的问题.我们的Oracle 12c数据库偶尔会在半夜的批处理循环中挂起.我们将不得不重新启动数据库以保持数天/周.然后又发生了.
经过一番挖掘,我们将其缩小到这个SQL:
UPDATE c_bill SET reason_desc = (SELECT description FROM codes
WHERE code_group = 'TRANSACTION_TYPE' AND code = c_bill.reason_code);
我已经重命名了表 – 但代码表有代码和描述.开发人员正在尝试将描述从此复制到c_bill表.
此SQL是作为批处理作业的一部分每晚运行的存储过程的一部分.开发人员在此之前进行了另一次更新,它经过了很好的处理,但是这个SQL需要很长时间.
在特定运行期间,该表具有36308行.当我检查生产数据库(我查看v $sql表中的SQL)时,我看到以下内容:
Rows_processed为第一次更新36308
Rows_processed用于上述更新1318270864,并且很高兴为= 36308 * 36308 !! (笛卡尔积?)
我们在TEST中没有这个问题.当我尝试UPDATE并解释在TEST中计划它时没问题 – 它在UPDATE和v $sql中都显示了36308行.
这令人费解.有没有人在SQL中看到笛卡尔积的机会?或者您是否了解Oracle 12c优化器中可能将其转换为笛卡尔积的任何错误(我们只是应用了一些修补程序来修复Group by!).
我对Oracle有相当多的经验 – 我在这里调整查询.我建议开发人员添加where条件以确定.我们还没有测试过.与此同时,我想通过Oracle专家来接受它.任何意见/建议非常感谢.
更新:对于将来看这篇文章的人 –
问题不是笛卡尔积,而是问题UPDATE sql在同一个表上的游标循环中运行,因此看起来像笛卡儿.见贾斯汀的回答.
最佳答案 我的第一个想法是试图收集证据,证实或反驳你有一个糟糕的计划做笛卡尔积的理论.在v $sql 1中执行了吗?还是36308?如果它是1,那将支持笛卡尔积理论,我将开始在v $sql_plan或dba_hist_sql_plan中查找查询计划,具体取决于何时发生以及您是否获得使用AWR的许可.另一方面,如果它是36308,则意味着查询正在更新36308行,但是有些东西导致它被调用36308次,因为某些东西试图遍历表中的每一行.