【问题标题】:Finding gaps in huge event streams?在巨大的事件流中寻找差距?
【发布时间】:2015-08-17 02:33:40
【问题描述】:

我在 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 中也有数据。

执行此查询的最佳方式是什么?

【问题讨论】:

  • 事件是否由单个时间点(而不是时间跨度)定义?
  • 你想要每个流都这样吗?换句话说,差距在属于单个流的事件之间?
  • @MOehm 是的,一个时间点
  • 您也需要 MongoDB 的解决方案吗?
  • 您能给我们展示一个 MongoDB 中的示例文档和预期的输出吗?

标签: sql mongodb algorithm postgresql bigdata


【解决方案1】:

在 postgres 中,借助 lag() 窗口函数可以很容易地完成。以下面的小提琴为例:

SQL 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'

Results

| id | stream_id |              timestamp |               pre_time | pre_id |
|----|-----------|------------------------|------------------------|--------|
|  4 |         7 | June, 01 2015 15:25:30 | June, 01 2015 15:20:32 |      3 |

【讨论】:

    【解决方案2】:

    您可以使用lag() 窗口函数在按时间戳排序的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");
    

    【讨论】:

      猜你喜欢
      • 2020-09-16
      • 2021-02-12
      • 1970-01-01
      • 2017-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-29
      • 2012-08-14
      相关资源
      最近更新 更多