postgresql中唯一的随机时间戳

时间:2014-03-09 10:00:24

标签: sql postgresql random timestamp

我正在努力做很多个小时。我需要创建100.000行,时间戳是主键。这就是为什么它必须是唯一的。

我写了一些代码,它可以生成100个随机时间戳,但如果我尝试超过100个,如1000或10000,我有一个错误,就像那样

  

错误:重复键值违反了唯一约束“position_pkey”   SQL状态:23505详细信息:密钥(“timestamp”)=(2014-03-09   04:03:16.843499)已经存在。

我不知道如何创建100.000时间戳唯一。

这是我的功能

CREATE OR REPLACE FUNCTION generate_random(count integer DEFAULT 1)
  RETURNS SETOF timestamp AS
$BODY$
    BEGIN
            RETURN QUERY SELECT distinct NOW()::timestamp + '10ms'::interval *RANDOM()*RANDOM()
FROM generate_series(0,count);

            --SELECT (NOW() - '10000000'::INTERVAL * ROUND(RANDOM() * RANDOM()))::timestamp
                    --     FROM GENERATE_SERIES(1, count);
        END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 1000;

这是generate_random函数,可以随机生成双数。

CREATE OR REPLACE FUNCTION generate_random(c integer DEFAULT 1, min double precision DEFAULT 0.0, max double precision DEFAULT 1.0)
  RETURNS SETOF double precision AS
$BODY$
        BEGIN
            RETURN QUERY SELECT min + (max - min) * RANDOM()
                         FROM GENERATE_SERIES(1, c);
        END;
    $BODY$
  LANGUAGE plpgsql VOLATILE STRICT
  COST 100
  ROWS 1000;

我在查询中将此函数称为

INSERT INTO "mytable"(
            "timestamp", x, y, z)
    VALUES (generate_random(1000), generate_random(1000, 0, 50), generate_random(1000, 0, 50), generate_random(1000, 0, 50));

所以,我想创建100.000行,这些行是唯一的时间戳和一些随机的双数字(无论是否独特)

3 个答案:

答案 0 :(得分:1)

保证唯一时间戳的唯一方法是在插入之间添加延迟。相反,您可以使用序列

create table mytable (
    s serial primary key,
    ts timestamp,
    x int,
    y int,
    z int
);
insert into mytable (ts, x, y, z) 
select 
    clock_timestamp(),
    500 * RANDOM(),
    500 * RANDOM(),
    500 * RANDOM()
from generate_series(1, 1000)
;

答案 1 :(得分:1)

There's a function on the PostgreSQL wiki, pseudo_encrypt, that will produce pseudo-random values distributed across the 32-bit integer space

使用feistel cypher从序列进行1:1映射的相同方法可用于时间戳。

或者您可以使用非重复的迭代伪随机数生成器。

主要的是,如果将结果缩小到较小的空间,则必须小心,因为会出现碰撞。

答案 2 :(得分:0)

permuteseq扩展名可以是 用于生成包含具有随机外观的唯一值的区间 分布。

这是一个在其中生成100000个唯一时间戳的示例 10000000(1000万)个可能的值,基于 将伪随机序列中的元素乘以10ms个区间 已添加到now()

CREATE EXTENSION permuteseq;

CREATE TABLE uniq_tstamp(t timestamp);

INSERT INTO uniq_tstamp
 SELECT now()+range_encrypt_element(elt, 1, 10000000, 1234::bigint) * '10ms'::interval AS t
 FROM  generate_series(1,100000) AS elt;

1234常量是一个混淆密钥:选择您想要获得不同系列结果的任何其他bigint

如果我们根据值的单一性和区间大小检查结果:

 SELECT min(t),max(t),count(distinct t) FROM uniq_tstamp ;

            min             |            max             | count  
----------------------------+----------------------------+--------
 2017-02-02 16:00:50.750651 | 2017-02-03 19:47:30.350651 | 100000
(1 row)

查看第一个值:

 SELECT * FROM uniq_tstamp limit 10;
             t              
----------------------------
 2017-02-03 14:42:44.420651
 2017-02-03 11:40:37.200651
 2017-02-02 17:28:50.470651
 2017-02-03 00:34:12.060651
 2017-02-03 00:02:16.780651
 2017-02-03 05:53:41.550651
 2017-02-02 21:53:49.900651
 2017-02-03 02:58:37.420651
 2017-02-03 05:25:00.730651
 2017-02-03 09:13:42.110651

permuteseq应用的随机化不是加密级别的,但它是合理的。