我已经根据前端应用程序传递的输入编写了PL / SQL代码来更新表的列,例如如果https://
,则以下块将运行。我有90多个这样的应用程序,并在过程中运行更新。在fetch()
中对其进行测试期间,尽管代码工作正常并且可以完成预期的工作,即先将列值设置为零,然后再调用几个函数进行财务处理计算,它花费的时间太长(超过一个小时)。最初,我认为这是因为有数以百万计的行/数据,但是我将其发布在此处,以检查代码是否有进一步改进的可能,以减少执行时间。
提前感谢您的帮助!
PS:我无法更改函数,例如INSTTABLE = 8
内部calc / return值,因为它在prod中被许多其他proc使用,因此我在单独的update语句中将列设置为0 ,然后进行主要更新。将其设置为零的原因是生产遵循相同的逻辑,即先将列设置为0,然后再进行计算。如果我不这样做,则比较查询会有所不同。
dev environment
BAS2_RWA_CALC
答案 0 :(得分:1)
在MERGE语句中,您有59个函数调用。好多啊。看来您MORT_BACK_SEC
中的每一行都在调用'BAS2_RWA_CALC'27次,即使您不使用这些调用的结果。现在,数据库可能已经足够聪明了,只能对您实际上从MORT_BACK_SEC
开始使用的行进行那些调用,但是我不会指望这一点。如果其他地方不需要它们(我看不到它们是),我建议将这些计算推入WHEN MATCHED
块中。对于每次进行的更新,您还将呼叫BAS2_MGRL_CAPITAL
和BAS2_EL_CALC
16次。我不知道这些函数有多复杂,但是如果它们很简单并且可以用内联CASE
表达式或类似的表达式替换,那么我会这么做,因为这么多的函数调用将导致性能下降。这个说法。我不知道这会生成什么样的计划,但是我怀疑这很重要-我怀疑该语句的运行时间将由所有这些函数调用的执行时间所控制。
我会尝试为您重新排列MERGE
语句,但是我不知道哪些函数参数是MORT_BACK_SEC
中的列,哪些是在MERGE
语句之外定义的变量。尝试尽可能多地从语句本身中分解出函数调用(如果有的话),当然可以将它们从初始MERGE
表中删除。 IMO您的MERGE
应该以
MERGE INTO MORT_BACK_SEC a
USING RPT_ACCT_HIER b
ON (a.GL_ACCOUNT_ID = b.ACCT_MEMBER AND
a.AS_OF_DATE = V_DATE AND
b.ACCT_GEN2 = 'a1000')
然后从那里拿走。
当然,由于您没有WHEN NOT MATCHED THEN INSERT
,因此您可以将所有这些函数调用移至UPDATE
中,而不用MERGE
来重做。 UPDATE
块。由你决定。但是我再次怀疑这很重要,因为这些函数调用是我怀疑该语句花费时间的地方。
好运。
答案 1 :(得分:1)
有几种方法可以减少SQL和PL / SQL之间的上下文切换的开销。
PRAGMA UDF;
在第一个is
之后,在代码中添加pragma udf;
,以告诉Oracle优化SQL函数。在我的快速测试中,这将SQL调用中的上下文切换开销减少了60%。这种方法的问题在于,它需要修改每个人的功能,并且在PL / SQL中调用时可能会导致性能下降。PRAGMA UDF;
的包装函数如果无法直接修改该函数,请在旧函数之上创建新函数,并使用pragma udf;
创建它们,然后调用它们SQL中的函数。我的测试表明,这可以将上下文切换减少52%,虽然不如以前的解决方案好,但是非常接近。这种方法将所有原始逻辑保留在同一位置,从而保留了“不重复自己”规则。但是,它确实会创建新对象。WITH
函数在SQL语句中将包装函数创建为公用表表达式。这样可以将开销减少大约32%。这是一种纯SQL方法,但是没有其他解决方案快,并且SQL语句看起来很丑。这些对您不起作用,但对于将来的读者来说,值得注意的是,最佳选择是: