【发布时间】:2021-07-03 17:49:58
【问题描述】:
我在 PostgreSQL 13 中有一个简单的表 tableA,其中包含事件计数的时间序列。在程式化的形式中,它看起来像这样:
event_count sys_timestamp
100 167877672772
110 167877672769
121 167877672987
111 167877673877
... ...
两个字段都定义为numeric。
借助 stackoverflow 的答案,我能够创建一个查询,该查询基本上计算给定时间跨度内正负过量事件的数量,以当前事件计数为条件。查询如下所示:
SELECT t1.*,
(SELECT COUNT(*) FROM tableA t2
WHERE t2.sys_timestamp > t1.sys_timestamp AND
t2.sys_timestamp <= t1.sys_timestamp + 1000 AND
t2.event_count >= t1.event_count+10)
AS positive,
(SELECT COUNT(*) FROM tableA t2
WHERE t2.sys_timestamp > t1.sys_timestamp AND
t2.sys_timestamp <= t1.sys_timestamp + 1000 AND
t2.event_count <= t1.event_count-10)
AS negative
FROM tableA as t1
查询按预期工作,并在此特定示例中为每一行返回给定时间窗口(+ 1000 [毫秒])的正负超额计数(范围 + / - 10)。
但是,我必须对具有数百万(甚至可能超过 100+ 百万)条目的表运行此类查询,即使有大约 50 万行,查询也需要很长时间才能完成。此外,虽然给定查询中的时间范围始终保持不变[但窗口大小可能因查询而异],但在某些情况下,我将不得不使用可能 10 个附加条件,类似于同一查询中的正/负超额.
因此,我正在寻找改进上述查询的方法,主要是考虑到设想数据集的大小,然后考虑更多条件,以实现更好的性能。
我的具体问题:
-
如何重用子查询的公共部分以确保它不会被执行两次(或多次),即如何在查询中重用它?
(SELECT COUNT(*) FROM tableA t2 WHERE t2.sys_timestamp > t1.sys_timestamp AND t2.sys_timestamp <= t1.sys_timestamp + 1000) -
将当前为
numeric的sys_timestamp字段转换为时间戳字段并尝试使用任何PostgreSQL Windows 函数是否有一些性能优势? (不幸的是,我对此没有足够的经验。) -
除了重用(部分)子查询以显着提高大型数据集的性能之外,是否还有一些巧妙的方法可以重写查询?
-
这些类型的查询使用 Java、Scala、Python 等在数据库之外运行它们可能更快吗?
【问题讨论】:
-
样本数据和期望的结果真的很有帮助。
-
如果您提供(相关部分)表定义(
CREATE TABLE语句)显示数据类型和约束、现有索引和一些示例数据,这会容易得多。 Consider instructions for performance questions here.
标签: sql postgresql window-functions postgresql-performance conditional-aggregation