1

我有一个非常缓慢和简单的查询,我正在尝试改进,它的目的是获取第一次失败的单元的日期,如下所示:

select unit_id, min(fail_Date) fail_Date
    from failures
  having min(fail_date) between '24-aug-2012' and '25-aug-2012'
   group by unit_id

您可能会猜到 Unit_id 不是唯一的,它是标识失败单元的外键,在此表中,如果同一单元多次失败,我有多个记录。

我知道这不是最好的方法,但我无法控制表格,我必须照原样处理它们。

该表具有fail_date 和unit_id 的索引。

尽管如此,这个查询需要 10 秒,我想问一下,我怎样才能让它更快?但后来我用这种方式查询值,只需要 0.03 秒:

with fail_dates as
 (select unit_id, fail_date
    from failures
   where fail_date between '24-aug-2012' and '25-aug-2012')
select f.unit_id, min(f.fail_Date) fail_Date
  from fail_dates
 inner join failures f
    on fail_dates.unit_id= f.unit_id
 group by f.unit_id,fail_dates.fail_date
 having  min(f.fail_Date) = fail_dates.fail_date

它们都返回完全相同的记录,但是第二个记录要快 10 倍,现在我的问题是,这两个查询真的等效吗?为什么第二个要快得多?

谢谢你!

4

3 回答 3

3

我的结论已经改变,这个答案在很大程度上被重写了。

起初我以为你的 2 个查询是不同的,但在阅读了你的评论并重新检查了第二个查询后,我意识到它确实会给出相同的结果。两个查询都只返回最早失败在 2 天范围内的单元。

您的第一个查询很慢,因为它在逻辑上必须查看每个单元的所有故障日期。它可能正在执行全表(或索引)扫描。

您的第二个查询要快得多,因为它只计算在目标日期范围内发生故障的单元的最短故障日期。我猜想它是使用前缘上带有失败日期的索引来识别在目标范围内失败的单元。然后它可以使用前缘上带有单元 id 的索引来查找相关单元的最小故障日期。

以下查询应该等同于您的查询,并且它有可能比您的第二个查询快一点,尽管我不会指望它。我说它可能会更快,因为此查询可以在找到任何具有早期失败日期的记录后立即消除一个单元,而您的第二个查询必须在逻辑上查看该单元的所有失败日期。只要这个查询不比你的第二个查询慢,我会选择这个,因为我认为逻辑更直接,更容易理解。

select unit_id,
       min(fail_Date) fail_Date
  from failures f
 where fail_date between '24-aug-2012' and '25-aug-2012'
   and not exists (
          select 1
            from failures f2
           where f2.unit_id=f1.unit_id
             and f2.fail_date < '24-aug-2012'
       )
 group by unit_id
于 2012-08-25T00:15:13.043 回答
2

我认为如果您将原始查询重写为

select unit_id, min(fail_Date) fail_Date
  from failures
  where fail_date between '24-aug-2012' and '25-aug-2012'
  group by unit_id

我希望这与您的第二个查询一样好。此查询和您的第二个查询运行得更快的原因是因为您首先通过仅选择那些在所需范围内具有 FAIL_DATE 的记录来子集表 - 这可能允许使用索引。原始查询必须扫描整个表,因为没有 WHERE 子句来帮助它只挑选出感兴趣的记录。

您可能想查看这两个查询的 EXPLAIN PLAN 输出,以了解它们是如何被评估的。

分享和享受。

于 2012-08-24T22:13:18.200 回答
1

如果不仔细观察它们,我会说它们是等效的,因为现在它们返回相同的行。不要指望它继续。

但是第二个版本中的公用表表达式(CTE)有一个非常严格的 WHERE 子句,只能选择两天的行。那个限制性的 WHERE 子句应该大大减少 GROUP BY 和 HAVING 必须做的工作。

您应该能够通过查看执行计划(pdf,白皮书)来确定。

于 2012-08-24T22:12:15.253 回答