提高sql查询速度

时间:2012-05-29 18:54:15

标签: sql database oracle10g

我有以下sql需要很长时间才能执行,有没有更好的方法来编写它来提高速度。

任何帮助都非常值得赞赏。

由于

    SELECT a.KeyField
    FROM Details a,
         Master b
    WHERE a.ForeignKeyField = b.ForeignKeyField
      AND a.KeyField IS NOT NULL
      AND Date BETWEEN 
TO_DATE ('01-01-2011', 'dd-mm-yyyy') AND TO_DATE ('31-12-2011', 'dd-mm-yyyy')
      AND a.KeyField IN
        (SELECT p.KeyField
         FROM Details p,
              Master q
         WHERE q.ForeignKeyField = p.ForeignKeyField
           AND p.KeyField IS NOT NULL
           AND p.KeyField = a.KeyField
           AND q.FKField2 = b.FKField2
         GROUP BY p.KeyField,
                  q.Date HAVING COUNT (DISTINCT q.ForeignKeyField) > 1)
    GROUP BY b.Id,
             b.Name,
             b.ForeignKeyField,
             b.Date,
             a.ForeignKeyField,
             a.SomeOtherField,
             a.KeyField,
             b.EtcEtc

4 个答案:

答案 0 :(得分:1)

在您的查询上运行EXPLAIN,您将看到缓慢来自哪里。但是,一般情况下,如果您可以避免嵌套查询(IN语句)和DISTINCT,那么您的查询效果会更好。看看您是否可以在同一查询中两次加入DetailsMaster表并相应地放置索引

答案 1 :(得分:1)

首先,您需要学习正确的连接语法。我的猜测是,由于相关的子查询,Oracle正在选择次优的查询路径。我们将其更改为联接:

SELECT a.KeyField
FROM Details a join
 Master b
 on a.ForeignKeyField = b.ForeignKeyField join
 (SELECT p.KeyField, q.Date, q.FKField2
  FROM Details p join
       Master q
       on q.ForeignKeyField = p.ForeignKeyField
  WHERE p.KeyField IS NOT NULL AND
        q.FKField2 = b.FKField2
  GROUP BY p.KeyField, q.Date
  HAVING COUNT (DISTINCT q.ForeignKeyField) > 1
 ) t
 on a.KeyField = t.KeyField and
    b.FKField2 = t.FKField2
WHERE a.KeyField IS NOT NULL AND
  Date BETWEEN TO_DATE ('01-01-2011', 'dd-mm-yyyy') AND TO_DATE ('31-12-2011', 'dd-mm-yyyy') AND
GROUP BY b.Id, b.Name, b.ForeignKeyField, b.Date, a.ForeignKeyField, a.SomeOtherField, a.KeyField, 
     b.EtcEtc

以这种方式编写也让我意识到Date上没有条件,尽管在子查询中使用了它。这是对的吗?

答案 2 :(得分:0)

确保您已准备好相关指数。检查执行计划以验证它们实际上是否正在使用。在选择索引时,Oracle非常挑剔。

答案 3 :(得分:0)

我不了解内部查询的原因。我会这样简化:

SELECT a.KeyField
FROM Details a,
     Master b
WHERE a.ForeignKeyField = b.ForeignKeyField
  AND a.KeyField IS NOT NULL
  AND Date >= TO_DATE ('01-01-2011', 'dd-mm-yyyy')
  AND Date <= TO_DATE ('31-12-2011', 'dd-mm-yyyy')

GROUP BY b.Id,
         b.Name,
         b.ForeignKeyField,
         b.Date,
         a.ForeignKeyField,
         a.SomeOtherField,
         a.KeyField,
         b.EtcEtc
HAVING COUNT (DISTINCT q.ForeignKeyField) > 1

同时将BETWEEN替换为>=, <=将有助于