在巨大的事件流中寻找差距?
Finding gaps in huge event streams?
我在 PostgreSQL 数据库中有大约 100 万个这种格式的事件:
id | stream_id | timestamp
----------+-----------------+-----------------
1 | 7 | ....
2 | 8 | ....
大约有 50,000 个独立流。
我需要找到任意两个事件之间的时间超过特定时间段的所有事件。换句话说,我需要找到在特定时间段内没有事件的事件对。
例如:
a b c d e f g h i j k
| | | | | | | | | | |
\____2 mins____/
在这种情况下,我想找到 (f, g) 对,因为它们是紧邻间隙的事件。
我不在乎查询是否(那么)慢,即在 100 万条记录上,如果需要一个小时左右就可以了。然而,数据集将继续增长,所以希望如果它很慢,它可以理智地扩展。
我还有MongoDB里的数据。
执行此查询的最佳方式是什么?
在 postgres 中,可以借助 lag() window 函数轻松完成。以下面的 fiddle 为例:
PostgreSQL 9.3 架构设置:
CREATE TABLE Table1
("id" int, "stream_id" int, "timestamp" timestamp)
;
INSERT INTO Table1
("id", "stream_id", "timestamp")
VALUES
(1, 7, '2015-06-01 15:20:30'),
(2, 7, '2015-06-01 15:20:31'),
(3, 7, '2015-06-01 15:20:32'),
(4, 7, '2015-06-01 15:25:30'),
(5, 7, '2015-06-01 15:25:31')
;
查询 1:
with c as (select *,
lag("timestamp") over(partition by stream_id order by id) as pre_time,
lag(id) over(partition by stream_id order by id) as pre_id
from Table1
)
select * from c where "timestamp" - pre_time > interval '2 sec'
| id | stream_id | timestamp | pre_time | pre_id |
|----|-----------|------------------------|------------------------|--------|
| 4 | 7 | June, 01 2015 15:25:30 | June, 01 2015 15:20:32 | 3 |
您可以使用 lag()
window 函数在按时间戳排序的 stream_id 分区上执行此操作。 lag()
函数使您可以访问分区中的前几行;没有滞后值,它是前一行。因此,如果 stream_id 上的分区按时间排序,则前一行是该 stream_id 的前一个事件。
SELECT stream_id, lag(id) OVER pair AS start_id, id AS end_id,
("timestamp" - lag("timestamp") OVER pair) AS diff
FROM my_table
WHERE diff > interval '2 minutes'
WINDOW pair AS (PARTITION BY stream_id ORDER BY "timestamp");
我在 PostgreSQL 数据库中有大约 100 万个这种格式的事件:
id | stream_id | timestamp
----------+-----------------+-----------------
1 | 7 | ....
2 | 8 | ....
大约有 50,000 个独立流。
我需要找到任意两个事件之间的时间超过特定时间段的所有事件。换句话说,我需要找到在特定时间段内没有事件的事件对。
例如:
a b c d e f g h i j k
| | | | | | | | | | |
\____2 mins____/
在这种情况下,我想找到 (f, g) 对,因为它们是紧邻间隙的事件。
我不在乎查询是否(那么)慢,即在 100 万条记录上,如果需要一个小时左右就可以了。然而,数据集将继续增长,所以希望如果它很慢,它可以理智地扩展。
我还有MongoDB里的数据。
执行此查询的最佳方式是什么?
在 postgres 中,可以借助 lag() window 函数轻松完成。以下面的 fiddle 为例:
PostgreSQL 9.3 架构设置:
CREATE TABLE Table1
("id" int, "stream_id" int, "timestamp" timestamp)
;
INSERT INTO Table1
("id", "stream_id", "timestamp")
VALUES
(1, 7, '2015-06-01 15:20:30'),
(2, 7, '2015-06-01 15:20:31'),
(3, 7, '2015-06-01 15:20:32'),
(4, 7, '2015-06-01 15:25:30'),
(5, 7, '2015-06-01 15:25:31')
;
查询 1:
with c as (select *,
lag("timestamp") over(partition by stream_id order by id) as pre_time,
lag(id) over(partition by stream_id order by id) as pre_id
from Table1
)
select * from c where "timestamp" - pre_time > interval '2 sec'
| id | stream_id | timestamp | pre_time | pre_id |
|----|-----------|------------------------|------------------------|--------|
| 4 | 7 | June, 01 2015 15:25:30 | June, 01 2015 15:20:32 | 3 |
您可以使用 lag()
window 函数在按时间戳排序的 stream_id 分区上执行此操作。 lag()
函数使您可以访问分区中的前几行;没有滞后值,它是前一行。因此,如果 stream_id 上的分区按时间排序,则前一行是该 stream_id 的前一个事件。
SELECT stream_id, lag(id) OVER pair AS start_id, id AS end_id,
("timestamp" - lag("timestamp") OVER pair) AS diff
FROM my_table
WHERE diff > interval '2 minutes'
WINDOW pair AS (PARTITION BY stream_id ORDER BY "timestamp");