我有一个将事件记录到 Redshift 的后端,它为每个事件生成一个唯一的 ID。id 是一个序列号。
我有类似的东西(events
表):
+-------------------------+------+
| created_at | id |
+-------------------------+------+
| 2017-06-30 09:20:47 UTC | 100 |
| 2017-06-30 09:18:31 UTC | 101 |
| 2017-06-30 09:16:19 UTC | 102 |
| 2017-06-30 09:12:08 UTC | 103 |
| 2017-06-30 09:11:59 UTC | 104 |
| 2017-06-30 09:11:15 UTC | 105 |
| 2017-06-30 07:03:41 UTC | 106 |
+-------------------------+------+
我的任务不是每小时运行一次,将很少的记录移动到另一个表 ( deactivated_events
)。
我想验证在过去 3 小时内我没有使用id
序列丢失任何记录。首先我考虑过使用 generate_series 但这在 Redshift 中不存在。其他人建议制作一个只有 ID 的表,但是用整数填充数据库仍然很痛苦(这里是一个生成 100 万的例子
我想知道最好的方法是不使用 min max 并像这样计数:
WITH merged_events AS
(SELECT *
FROM
(SELECT id, created_at
FROM events
UNION
SELECT id, created_at
FROM deactivated_events
)
WHERE created_at > GETDATE() - INTERVAL '3 hours'
ORDER BY id)
SELECT COUNT(*), (max(id) - min(id) + 1) AS diff
FROM merged_events;
PS:奖金,如何找到丢失或重复的记录?
假设您有这样的设置:
和 ...
如果 Redshift 提供
Window Functions
,您可以使用查询的细微变化来做两件事:id
考虑分组时有重复的sid
,发现count > 1id
如果前一行的 不是 1 + 当前行,则认为缺少一行(或更多行!) 。这是通过LAG
函数完成的。这可以通过以下查询完成
这将产生:
您可以在dbfiddle此处检查整个设置(使用 PostgreSQL 而不是 RedShift)
注意事项
id
:如果它实际上来自一个IDENTITY
列(或者SEQUENCE
它的 Redshift 恰好实现了它,我认为情况并非如此),您可能会有差距。所以,你应该首先通过其他方式保证你的id最初是连续的......参考:
这听起来真是个坏主意。相反,我会敦促您创建一个新
active
的 type列bool
。特别是如果您需要合并该表中的事件。如果您停止从表中删除,那将不再是一个问题。
另外,请参阅@joanolo 关于序列的注释。在 Redshift上也是如此,
IDENTITY COLUMNS
通常,您不想将数据移出表以对其进行存档。特别是如果你不必这样做。PostgreSQL 10 即将发布。Redshift 很可能会升级到使用它。如果他们这样做,您将拥有价值分区,它将透明和自动地执行此操作。