[英]How to optimise this SQL Query
此查询花费了超过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中针对所有查询运行,因此需要很长时间
因为如果我退出最后2行,此sql将在3 secondes
给出结果
因此,任何优化方案
谢谢
如果没有计划和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,则不需要这种方法
如果问题出在过多的函数调用上,并且您使用的是Oracle的最新版本(我的观点是11g),则可以从子查询缓存中受益。
简单地将所有函数调用重写为子查询:
select * from t1
where (select Z_Id_Cpt_To_Val(Account_ID) from dual) between ...
如果您有很多记录和几个ACCOUNT_ID
或订购了ACCOUNT_ID
则此方法将起作用。
我想知道使用像这样的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)
上fact_acct(C_AcctSchema_ID, PostingType, DateAcct)
索引。
注意:假设函数对于给定的参数集返回相同的值,则可以将WHERE
子句中与该函数有关的条件简化为=
。
如果这样做没有帮助,您将需要深入研究该函数本身。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.