oracle优化查询

xa9qqrwz  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(273)

我正在使用oraclepl/sql,我有一个存储过程来处理这个查询,它有点复杂,但是它完成了任务,问题是它需要大约35分钟,sql开发人员autotrace说,它正在做一个完整的扫描,即使表有它们的索引。
那么有什么方法可以改进这个查询吗?

select tipotrx, sum(saldo) as saldo, 
count(*) as totaltrx from (
 select  max(ids) as IDTRX, max(monto) as monto, min(saldo) as saldo, max(aq_data) as aq_data, thekey, tipotrx
 from (
       select t.SID as ids, (TO_NUMBER(SUBSTR(P.P1, 18, 12))) as monto,
       ((TO_NUMBER(SUBSTR(P.P1, 18, 12)) * (TO_NUMBER(SUBSTR(t.acquirer_data, 13,2)) - 
       TO_NUMBER(SUBSTR(P.P4, 3,2))))) as saldo,
       (TO_CHAR(t.trx_date, 'YYMMDD') || t.auth_code || t.trx_amount || (SELECT 
       functions.decrypt(t.card_number) FROM DUAL)) as thekey,
       t.acquirer_data AS aq_data,
       TO_NUMBER(SUBSTR(t.acquirer_data, 12, 1)) as tipotrx
       from TBL_TRX t INNER JOIN TBL_POS P ON (t.SID = P.transaction) 
       WHERE (TO_NUMBER(SUBSTR(t.acquirer_data, 13,2)) >= TO_NUMBER(SUBSTR(P.P4, 3,2))) 
       AND trunc(t.INC_DATE)  between (TO_DATE('20/06/2020', 'DD/MM/YYYY') - 35) AND TO_DATE('20/06/2020', 'DD/MM/YYYY')
  ) t
  group by thekey,  tipotrx order by max(ids) desc) j 
group by tipotrx;

谢谢。

zlwx9yxi

zlwx9yxi1#

更改此项:

trunc(t.INC_DATE) between (TO_DATE('20/06/2020', 'DD/MM/YYYY') - 35)
                       AND TO_DATE('20/06/2020', 'DD/MM/YYYY')

对此:

t.INC_DATE between (TO_DATE('20/06/2020', 'DD/MM/YYYY') - 35)
                AND TO_DATE('21/06/2020', 'DD/MM/YYYY') - INTERVAL '1' SECOND

不需要构建基于函数的索引,您可以将 predicate 修改为可搜索的(能够使用索引)。而不是使用 TRUNC 要从列中减去,请在上限文字上加上一天减去一秒钟。
代码比较混乱,但应该能够利用索引。但是,35天的数据量可能很大;日期索引可能不是很有用,您可能需要查看其他 predicate 。

7gcisfzg

7gcisfzg2#

大多数情况下,索引必须完全匹配where子句中的内容才能使用。当您的where子句显示

TO_NUMBER(SUBSTR(t.acquirer_data, 13,2))

当where子句显示

trunc(t.INC_DATE)

操作where子句中的每一列,仅此一项就可能阻止使用任何普通索引。
但是,如果创建基于函数的索引,则可以创建一些与where子句中的内容匹配的新索引。这样,数据库至少有可能使用索引,而不是进行全表扫描。

--example function based index.
 CREATE INDEX TRUNC_INC_DATE ON TBL_TRX (trunc(t.INC_DATE));

当然,新索引会占用更多的空间,并增加自己的开销。继续用自动竞速看是否值得。
此外,更新表统计信息可能也不会有什么坏处。

相关问题