加入Oracle中的性能问题

时间:2013-09-11 14:04:12

标签: sql performance oracle database-performance

我们有两张桌子。

  1. 表 - XYZ - >拥有超过189个M记录
  2. 表格 - ABC - >只有1098条记录。
  3. 我们的联接查询有点像

    select a.a, a.b, a.c 
    from xyz a , ABC r 
    where a.d = r.d
        and a.sub not like '0%' 
        and ((a.eff_dat < sysdate) or (a.eff_date is null))
    

    这是我们的查询执行方式。无论如何,它都可以选择更快地执行。 除了不喜欢之外,你能否告诉我任何其他方法。

    在解释计划中,我已经看到它将189 M作为itrator并检查1098记录,这需要更多时间。 我从关键词之后交换了表格,但它也没有用。 尝试了领先的暗示,这也没有达到目的。 另外a.d列是一个索引的列,也用于提示。

    请建议任何优化方法。

2 个答案:

答案 0 :(得分:3)

如果表上有多个谓词,例如:

    a.sub not like '0%' 
and ((a.eff_dat < sysdate) or (a.eff_date is null))

......除非您使用动态采样,否则优化器不太可能准确估计结果集的基数,因此请查看解释计划以查看是否:

  1. 正在调用动态采样。
  2. 对基数的估计是正确的。
  3. 如果谓词不是非常有选择性 - 如果它们没有消除90%或表中的行 - 那么索引不太可能有助于查找行,并且完全扫描(如果以支持该分区的方式对表进行分区,则使用分区修剪)可能是最佳访问路径。

    我有理由相信,如果表之间存在外键(即rd中存在所有广告值),则最佳访问路径将是XYZ的完整扫描,并使用散列连接ABC。 顺便说一句,你提到提示但不包括在问题中。用假名隐藏表的目的也没有用,因为这些名称经常提供有关数据类型和数据集中值分布的有价值的线索。

答案 1 :(得分:0)

似乎大部分成本都在大表上的(假定的)全表扫描中。我建议重写你的WHERE条件如下:

SELECT * FROM XYZ A
WHERE SUBSTR(A.SUB, 1, 1) <> '0'
AND NVL(A.EFF_DAT, TO_DATE('01-01-0001', 'MM-DD-YYYY')) < SYSDATE ;

然后创建一个包含所有相关列的函数索引:

CREATE INDEX IX_XYZ1 ON
XYZ(NVL(EFF_DAT, TO_DATE('01-01-0001', 'MM-DD-YYYY')), SUB, D);

通过检查执行计划,确保基于成本的优化器正在获取新索引。

LIKE,NOT LIKE和OR操作数是你在WHERE条件下可以使用的最糟糕的事情。