【问题标题】:Make postgresql timestamps unique使 postgresql 时间戳唯一
【发布时间】:2016-01-20 08:17:30
【问题描述】:

我有一个包含 6M+ 行的数据集,包括从大约 2003 年到当前的时间戳。 2014年数据库迁移到postgresql,由于时间戳精度更高,时间戳列变得唯一。原始 ID 列未迁移。大约 300k 的时间戳至少重复一次。我想通过增加精度来修改时间戳列,使它们是唯一的(所有非唯一的时间戳只到第二个)。

我有这个

ts                    message
--------------------|---------------
2014-02-01 07:40:37 | message1
2014-02-01 07:40:37 | message2

我想要这个

ts                         message
-------------------------|---------------
2014-02-01 07:40:37.0000 | message1
2014-02-01 07:40:37.0001 | message2

【问题讨论】:

  • 真正的问题是,您是否绝对确定要使用时间戳作为键(我假设这就是您需要它们唯一的原因)?这些可能不是唯一的,原因不止一个……
  • 也许做一个'select group by ts'并循环结果并执行另一个选择并将每条记录加1?

标签: postgresql


【解决方案1】:

这应该可行,但我猜它会非常慢:

update the_table
  set ts = ts + '1 millisecond'::interval * x.rn
from (
   select ctid, row_number() over (order by ts) as rn
   from the_table
) x
where the_table.ctid = x.ctid;

ctid 列是 Postgres 维护的 internal unique identifier(实际上是行的物理地址)。

您可能想要添加另一个where 条件以仅选择那些需要修改的行。

【讨论】:

  • 我是否正确,这会修改每一行并基本上将它乘以它的行号?
  • @DannyDyla:是的,它会更新每一行,这就是为什么我在最后添加了“你可能想要添加另一个 where 条件”。它不会将 value 与行号相乘。乘法计算每行添加到时间戳值的毫秒数(基本上第一行:+1 毫秒,第二行:+2 毫秒,第 1000 行:+1 秒,依此类推)
  • 我会使用date_trunc('second', ts) = ts作为第二个条件
【解决方案2】:

一个简单的解决方案是尝试在时间戳中添加一个随机间隔:

update t
set ts = ts + random() * interval '1000000 microsecond'
where ts = date_trunc('second', ts)

发生碰撞的几率非常低。如果发生,请使用@a_horse's answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    相关资源
    最近更新 更多