此查询占用的时间超过4 minutes
,我想让它运行得更快。请提供任何建议
SELECT *
FROM fact_acct zz
WHERE zz.C_AcctSchema_ID=1000000
AND zz.PostingType ='A'
AND TRUNC(zz.DateAcct,'DD') BETWEEN TO_DATE('2016-01-01','YYYY-MM-DD') AND TO_DATE('2016-01-01','YYYY-MM-DD')
AND Z_Id_Cpt_To_Val(Account_ID) <= Z_Id_Cpt_To_Val(1001508)
AND Z_Id_Cpt_To_Val(Account_ID) >= Z_Id_Cpt_To_Val(1001508)
函数Z_Id_Cpt_To_Val ()
是问题的原因,它在这个SQL中运行所有查询,所以需要很长时间
因为如果我退出最后两行,这个sql会在3 secondes
中给出结果
所以,任何想要优化的想法
谢谢
答案 0 :(得分:1)
如果没有plan和ddl,那将只是假设。
第一个假设
你有关于fact_acct.DateAcct,TRUNC(fact_acct.DateAcct,'DD')的索引 - 不会使用索引 TRUNC(fact_acct.DateAcct,'DD')仅修剪小时/分钟/秒部分。 你可以使用
zz.DateAcct >= BETWEEN TO_DATE('2016-01-01','YYYY-MM-DD') <TO_DATE('2016-01-02','YYYY-MM-DD')
第二个假设
而不是
Z_Id_Cpt_To_Val(Account_ID) <= Z_Id_Cpt_To_Val(1001508)
把
(select Z_Id_Cpt_To_Val(Account_ID) from dual) <= (select Z_Id_Cpt_To_Val(1001508) from dual)
每次使用缓存机制时,Oracle都不会执行此功能。但要小心!如果您希望Oracle始终执行Z_Id_Cpt_To_Val,那么您不需要这种方法
答案 1 :(得分:0)
如果问题出现在过多的函数调用中,并且您使用的是最新版本的Oracle(11g中的东西),您可以从subquery caching中获利。
简单地重写对子查询的所有函数调用:
select * from t1
where (select Z_Id_Cpt_To_Val(Account_ID) from dual) between ...
如果您有大量记录和一些ACCOUNT_ID
或订购了ACCOUNT_ID
,这将有效。
答案 2 :(得分:0)
我想知道使用这样的CTE是否会有所帮助:
WITH zz as (
SELECT *
FROM fact_acct zz
WHERE zz.C_AcctSchema_ID = 1000000 AND
zz.PostingType = 'A' AND AND
zz.DateAcct >= TO_DATE('2016-01-01', 'YYYY-MM-DD') AND
zz.DateAcct < TO_DATE('2016-01-02', 'YYYY-MM-DD')
)
SELECT zz.*
FROM zz CROSS JOIN
(SELECT Z_Id_Cpt_To_Val(1001508) as cv FROM dual) x
WHERE Z_Id_Cpt_To_Val(Account_ID) = x.cv;
对于CTE,您需要fact_acct(C_AcctSchema_ID, PostingType, DateAcct)
上的索引。
注意:关于函数的WHERE
子句中的条件可以简化为=
,假设函数为给定的参数集返回相同的值。
如果这没有帮助,您将需要深入了解该功能本身。