我怎样才能产生一个随机的bytea


Answers:


20

增强Jack Douglas的答案以避免需要PL / PgSQL循环和bytea串联,您可以使用:

CREATE OR REPLACE FUNCTION random_bytea(bytea_length integer)
RETURNS bytea AS $body$
    SELECT decode(string_agg(lpad(to_hex(width_bucket(random(), 0, 1, 256)-1),2,'0') ,''), 'hex')
    FROM generate_series(1, $1);
$body$
LANGUAGE 'sql'
VOLATILE
SET search_path = 'pg_catalog';

这是一个简单的SQL函数,比PL / PgSQL调用起来便宜。

对于较大的bytea值,由于更改了聚合方法而导致的性能差异非常大。尽管对于小于50字节的大小,原始功能实际上快了3倍,但对于较大的值,此功能的伸缩性要好得多。

或使用C扩展功能

我已经实现了一个随机的bytea生成器作为简单的C扩展功能。它在我的GitHub的scrapcode存储库中。请参阅此处的自述文件。

它影响了上述SQL版本的性能:

regress=# \a
regress=# \o /dev/null
regress=# \timing on
regress=# select random_bytea(2000000);
Time: 895.972 ms
regress=# drop function random_bytea(integer);
regress=# create extension random_bytea;
regress=# select random_bytea(2000000);
Time: 24.126 ms

1
好吧,我想出了几乎相同的解决方案,但只测试了较低的值。@Jack的解决方案显然是赢家。为您+1而不是在这里停止:)
dezso 2012年

谢谢-这太好了,令人发指。我认为FROM generate_series(0, $1);需要FROM generate_series(1, $1);。您是否尝试过递归?我的有限测试表明,这种方法可以更好地进行扩展:
杰克·道格拉斯

2
我试图符号链接/dev/urandom/var/lib/pgsql/data与阅读它pg_read_file()奖金疯狂点,但不幸的是pg_read_file()text经编码的转换输入,所以它无法读取BYTEA。如果您确实想要最大速度,请编写一个C扩展函数,该函数使用快速的伪随机数生成器生成二进制数据,并在缓冲区周围包裹一个字节数据:-)
Craig Ringer 2012年

1
@JackDouglas我无奈。的C扩展版本random_byteagithub.com/ringerc/scrapcode/tree/master/postgresql/…–
Craig Ringer

1
另一个极好的答案!实际上,这是迄今为止我见过的最好的之一。我尚未测试该扩展程序,但我相信它可以像宣传的那样工作。
Erwin Brandstetter,2012年

5

我希望能够生成任意长度的随机bytea字段

此函数可以完成此操作,但是1Gb将花费很长时间,因为它不会随输出长度线性缩放:

create function random_bytea(p_length in integer) returns bytea language plpgsql as $$
declare
  o bytea := '';
begin 
  for i in 1..p_length loop
    o := o||decode(lpad(to_hex(width_bucket(random(), 0, 1, 256)-1),2,'0'), 'hex');
  end loop;
  return o;
end;$$;

输出测试:

select random_bytea(2);

/*
|random_bytea|
|:-----------|
|\xcf99      |
*/

select random_bytea(10);

/*
|random_bytea          |
|:---------------------|
|\x781b462c3158db229b3c|
*/

select length(random_bytea(100000))
     , clock_timestamp()-statement_timestamp() time_taken;

/*
|length|time_taken     |
|-----:|:--------------|
|100000|00:00:00.654008|
*/

dbfiddle 在这里


很好地使用width_bucket。便利。
Craig Ringer

1
我已经增强了避免PL / PgSQL和昂贵的串联循环的方法。看到新的答案。通过在generate_series上使用string_agg代替bytea上的PL / PgSQL串联循环,我发现性能提高了150倍。
Craig Ringer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.