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

Dav*_*vid 1 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;
Run Code Online (Sandbox Code Playgroud)

Mat*_*lie 5

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

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

如果您将查询重新设置为"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
;
Run Code Online (Sandbox Code Playgroud)

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

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

编辑

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

编辑

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