2016-01-20 164 views
1

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

我有这个

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 
+3

真正的问题是,你绝对确定你想使用时间戳作为键(我假设这就是你需要他们是唯一的)?由于多种原因,这些可能不是唯一的... – CptBartender

+1

也许使用'select group by ts'并循环结果并执行另一个select并将每个记录添加1? – kometen

回答

0

这应该工作,但是这将是可怕的慢我猜:

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; 

ctidinternal unique identifier (实际上是该行的物理地址)由Postgres维护。

您可能想要添加另一个where条件来只挑出那些需要修改的行。

+0

我是否正确,这将修改每一行,只是乘以它的行号? –

+0

@DannyDyla:是的,它会更新每一行,这就是为什么我在最后添加了“你可能会添加另一个条件”。它不会将_value_与行号相乘。乘法计算每个被添加到时间戳值的行的毫秒数(基本上第一行:+1毫秒,第二行:+2毫秒,行#1000:+1秒等等) –

+1

我将使用'date_trunc ('second',ts)= ts'作为第二个条件 –

0

一个简单的解决办法就是尽量随机间隔添加时间戳:

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

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