繁体   English   中英

如何优化此SQL查询

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM