如何优化这个“分时”SQL查询?

时间:2011-03-17 09:32:42

标签: sql postgresql

我希望能够轻松地在我的时间序列数据上运行查询,例如以下查询:

“彼此在七天之内发生的最典型事件是什么?”

我可以通过利用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;

1 个答案:

答案 0 :(得分:5)

部分问题是某些功能阻止RDBMS能够推断查询的某些属性,然后搜索任何索引。 (查看SARGABLE了解更多信息。)

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

如果您将查询改为“在哪里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
;

现在,RDBMS应该能够更轻松地使用涵盖[thetimeanddate]字段的表上的任何索引。它现在只计算出你拥有的2900万个事件中每个事件的截断日期,并检查索引以查看在“此日期”和“该日期”之间出现的数量。可能比替代品快几百万倍......

(我也很想将WHERE子句移动到ON子句中,但仅用于样式目的。性能将是相同的。记住,RBDMS编译这些查询,并选择算法和优化。如果两个查询可以代数操纵相同,它们通常会产生相同的最终执行计划。[假设操作所需的所有信息都存在于查询中,而不是“只知道你的头脑”。)

修改

我还注意到你是通过a.eventID和b.eventID进行分组,然后进行计数。假设eventID在表中是唯一的,这将总是产生1 ...

的计数

修改

将+5更改为+ INTERVAL'5天'