如何优化这一点;“时间间隔”;SQL查询?

如何优化这一点;“时间间隔”;SQL查询?,sql,postgresql,Sql,Postgresql,我希望有一种简单的方法来对我的时间序列数据运行查询,如以下查询: “相隔七天内最典型的事件是什么?” 我可以通过使用SQL和Java程序来做到这一点,通过查看每一行并运行一个查询,查询会在七天之前或之后查找所有事件,但这不是很优雅,性能会很糟糕 我还得到了JNK和Milen A.Radev的帮助来编写以下SQL。我的问题是,当我在2300万行上测试时,它运行了两个小时,然后停止了,因为我的RamDisk(我运行PostgreSQL数据库的地方)已满。你知道我如何优化这样一个查询吗 SELECT

我希望有一种简单的方法来对我的时间序列数据运行查询,如以下查询:

“相隔七天内最典型的事件是什么?”

我可以通过使用SQL和Java程序来做到这一点,通过查看每一行并运行一个查询,查询会在七天之前或之后查找所有事件,但这不是很优雅,性能会很糟糕

我还得到了JNK和Milen A.Radev的帮助来编写以下SQL。我的问题是,当我在2300万行上测试时,它运行了两个小时,然后停止了,因为我的RamDisk(我运行PostgreSQL数据库的地方)已满。你知道我如何优化这样一个查询吗

SELECT a.eventID, b.eventID, COUNT(*)
FROM table a
INNER JOIN table b
    ON a.eventID <> b.eventID
WHERE aBS(EXTRACT(EPOCH FROM (a.thetimeanddate - b.thetimeanddate))) < 5 
GROUP BY a.eventID, b.eventID 
ORDER BY COUNT(*) DESC
LIMIT 1000;
选择a.eventID、b.eventID、COUNT(*)
从表a
内部联接表b
关于a.eventID b.eventID
式中aBS(摘录(历元自(a.时间和日期-b.时间和日期))<5
按a.eventID、b.eventID分组
按计数排序(*)说明
限1000;

部分问题在于某些函数阻止RDBMS推断查询的某些属性,然后搜索任何索引。(有关这方面的更多信息,请查阅SARGABLE。)

这意味着RDBMS必须处理每个事件组合,并检查WHERE caluse,以查看它们是否在彼此的5天内。每个组合等于52900000000000个组合。(5.29亿相当可观。)

如果您将查询改为“WHERE b.thetimeanddate具有这些属性”,那么您可能会发现性能有所提高。如果索引包含[TimeandDate]字段,则会发生这种情况。例如

SELECT
  a.eventID,
  b.eventID,
  COUNT(*)
FROM
  table a
INNER JOIN
  table b
    ON a.eventID <> b.eventID
WHERE
      b.thetimeanddate >= date_trunc('day', a.thetimeanddate) - INTERVAL '5 days'
  AND b.thetimeanddate <  date_trunc('day', a.thetimeanddate) + INTERVAL '6 days'
GROUP BY
  a.eventID,
  b.eventID
ORDER BY
  COUNT(*) DESC
LIMIT
  1000
;
选择
a、 eventID,
b、 eventID,
计数(*)
从…起
表a
内连接
表b
关于a.eventID b.eventID
哪里
b、 时间和日期>=日期(天),a.时间和日期-间隔“5天”
和b.时间和日期
RDBMS现在应该能够更容易地利用表中包含[TimeandDate]字段的任何索引。它现在只计算出2900万个事件中每个事件的截断日期,并检查一个索引,看看有多少出现在“这个日期”和“那个日期”之间。很可能比另一种方法快几百万倍

(我也会尝试将WHERE子句移到ON子句中,但仅出于样式目的。性能将是相同的。请记住,RBDM编译这些查询,并选择算法和优化。如果两个查询可以通过代数操作成为相同的,它们通常会产生相同的最终执行计划。[假设操作所需的所有信息都存在于查询中,并且不是“仅在您的头脑中才知道”。]

编辑

我还注意到,您同时按a.eventID和b.eventID进行分组,然后进行计数。假设eventID在表中是唯一的,这将始终产生1的计数

编辑


将+5改为+INTERVAL“5天”

部分问题在于某些函数阻止RDBMS推断查询的某些属性,然后搜索任何索引。(有关此项的详细信息,请查阅SARGABLE。)

这意味着RDBMS必须处理每一个事件组合,并检查WHERE caluse,以查看它们是否在相互之间的5天内。每一个组合相当于529000000000000个组合。(52900000000000个组合相当多。)

如果您将查询改为“WHERE b.thetimeanddate具有这些属性”,那么您可能会发现性能提升。如果索引覆盖了[thetimeanddate]字段,则会出现这种情况。例如

SELECT
  a.eventID,
  b.eventID,
  COUNT(*)
FROM
  table a
INNER JOIN
  table b
    ON a.eventID <> b.eventID
WHERE
      b.thetimeanddate >= date_trunc('day', a.thetimeanddate) - INTERVAL '5 days'
  AND b.thetimeanddate <  date_trunc('day', a.thetimeanddate) + INTERVAL '6 days'
GROUP BY
  a.eventID,
  b.eventID
ORDER BY
  COUNT(*) DESC
LIMIT
  1000
;
选择
a、 eventID,
b、 eventID,
计数(*)
从…起
表a
内连接
表b
关于a.eventID b.eventID
哪里
b、 时间和日期>=日期(天),a.时间和日期-间隔“5天”
和b.时间和日期
RDBMS现在应该能够更容易地利用表中包含[TimeandDate]字段的任何索引。它现在只计算出2900万个事件中每个事件的截断日期,并检查索引以查看在“this date”和“that date”之间出现了多少个.可能比另一种方法快几百万倍

(我也会尝试将WHERE子句移到ON子句中,但仅出于样式目的。性能将是相同的。请记住,RBDM编译这些查询,并选择算法和优化。如果两个查询可以通过代数操作成为相同的,它们通常会产生相同的最终执行计划。[假设操作所需的所有信息都存在于查询中,并且不是“仅在您的头脑中才知道”。]

编辑

我还注意到,您同时按a.eventID和b.eventID进行分组,然后进行计数。假设eventID在表中是唯一的,这将始终产生1的计数

编辑


将+5更改为+INTERVAL“5天”

您的查询不会“提前或推迟七天查找事件”。它只返回表a中所有在表be中有匹配行的行,并计算两列之间的差。@a\u horse\u和\u no\u name您完全正确。我选择了错误的SQL查询。我已更新了我的问题。@David:您确定a.eventID b.eventID
条件下的
吗?这不会加入相应的行s和可能会生成一个巨大的结果集。@a_horse_和_no_name我同意这是一个非常广泛的连接,但我不知道如何使它更具限制性。使用where子句可以减少最终输出,但也许我应该移动where c