我希望能够轻松地在我的时间序列数据上运行查询,例如以下查询:
“彼此在七天之内发生的最典型事件是什么?”
我可以通过利用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;
答案 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天'