2012-05-29 191 views
0

我有以下SQL这需要很长的时间来执行,有没有写这个改善的速度没有更好的办法。提高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 
+1

喜欢JOIN到的连接表,始终做到'SmallTable INNER JOIN BigTable'。 – MPelletier

+0

@MPelletier很棒的信息!你能解释为什么SmallTable INNER JOIN BigTable –

+0

你的索引是什么? – HLGEM

回答

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 

写作这种方式也让我认识到,有在日期没有条件,尽管这是在子查询中使用。它是否正确?

+0

日期时间用于外部查询,因为我有条件'entry_date BETWEEN' – user75ponic

+0

有了JOIN,而不是在哪里提高了速度,明天我会为结果做一个彻底的测试。非常感谢。 – user75ponic

+0

当我做了一个小测试时,我注意到有很多用查询检索到的行。这是因为当我执行时,我从查询中删除了sh_status_code部分?但我会做一个彻底的测试。 – user75ponic

0

请确保您有相关的指标到位。检查执行计划以确认它们实际上正在使用。 Oracle在选择索引时相当挑剔。

1

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

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将有助于

+1

不要鼓励隐式连接的sql反模式 – HLGEM

+0

你能解释一下反模式? –

+0

顺便说一下,我非常尊重你,原因如下:1.你在过去帮助过很大,2.你不害怕提问(即使其他用户有高分)3。你没有一个用来隐藏你的低调回答的幽灵帐户,不像其他高调用户 –