Oracle DB 上的自加入性能



我有一个自我连接,在oracle DB上非常慢。我已经在所有相关领域放置了索引。有人对如何提高性能有建议吗?

select count(tNew.idtariffa)  CONT  
from tariffe tAtt 
join tariffe tNew on tAtt.idtariffa = tNew.idtariffa 
where (tAtt.stato_attivo = 't') 
and (tNew.stato_attivo = 'f') 
and (tAtt.validity_date < tNew.validity_date) 
and (tAtt.dataimport < tNew.dataimport) 
and (tNew.validity_date < to_date('2017-6-26','YYYY-MM-DD'))

尝试PUSH_PRED提示:

select /*+ NO_MERGE(tNew) PUSH_PRED(tNew) */
count(tNew.idtariffa)  CONT  
from tariffe tAtt 
join tariffe tNew on tAtt.idtariffa = tNew.idtariffa 
where (tAtt.stato_attivo = 't') 
and (tNew.stato_attivo = 'f') 
and (tAtt.validity_date < tNew.validity_date) 
and (tAtt.dataimport < tNew.dataimport) 
and (tNew.validity_date < to_date('2017-6-26','YYYY-MM-DD'))

Exists版本值得一试:

select count(1) cont
from tariffe n
where stato_attivo = 'f'
and validity_date < date '2017-06-26'
and exists ( select null
from tariffe
where idtariffa = n.idtariffa
and stato_attivo = 't'
and validity_date < n.validity_date
and dataimport < n.dataimport )

没有数据量、数据倾斜、索引定义、解释计划等细节的性能调优只是猜测。

所以这里有更多的猜测:)

你的驱动表应该是tariffe tNew的,因为这是你用来在结果集顶部的那个。

tNew.validity_date < to_date('2017-6-26','YYYY-MM-DD'))

现在,除非tNew.stato_attivo = 'f'非常有选择性,否则您将检索表中所有行的一大块(取决于记录的回退距离(,因此全表扫描将是获取这些记录的最有效方法。

tariffe tAtt上的联接是有问题的idtariffa因为它不是唯一的列。因此,联接是一组tNew记录与一组tAtt记录。这些将使用 WHERE 子句中的条件在内存中筛选。

"我已经在所有相关字段上放置了索引">

单列索引在这里无济于事。您可能会从所有相关列的复合索引中获得一些乐趣:

tariffe (stato_attivo , validity_date, idtariffa, dataimport) 

如果您经常运行此查询,这将值得构建。

还有其他猜测吗?子查询分解以命中主表一次。如果tariffe有很多列,只执行一次全表扫描会加快速度。

with cte as ( 
select stato_attivo , validity_date, idtariffa, dataimport
from tariffe
where validity_date < to_date('2017-6-26','YYYY-MM-DD'
)
select count(tNew.idtariffa)  CONT  
from cte tNew 
join cte tAtt on tAtt.idtariffa = tNew.idtariffa 
where (tAtt.stato_attivo = 't') 
and (tNew.stato_attivo = 'f') 
and (tAtt.validity_date < tNew.validity_date) 
and (tAtt.dataimport < tNew.dataimport) 

最新更新