무작위 bytea를 생성하는 방법


18

bytea테스트 데이터를 채우기 위해 임의 길이 (<1Gb)의 임의 필드 를 생성하고 싶습니다 .

가장 좋은 방법은 무엇입니까?

답변:


20

PL / PgSQL 루핑 및 bytea 연결의 필요성을 피하기 위해 Jack Douglas의 답변을 강화하면 다음을 사용할 수 있습니다.

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';

SQLPL / PgSQL보다 호출 비용이 저렴한 간단한 기능입니다.

변경된 집계 방법으로 인한 성능 차이는 큰 bytea값일 경우 엄청납니다 . 원래 함수는 <50 바이트 크기의 경우 실제로 최대 3 배 더 빠르지 만 더 큰 값의 경우 훨씬 더 잘 확장됩니다.

또는 C 확장 기능을 사용하십시오 .

임의의 bytea 생성기를 간단한 C 확장 함수로 구현했습니다. 그것은 내에서의 GitHub의에 scrapcode 저장소 . README를 참조하십시오.

위 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

감사합니다-이것은 훌륭하고 생각을 자극합니다. 생각 FROM generate_series(0, $1);해야합니다 FROM generate_series(1, $1);. 재귀를 시도 했습니까? 제한적인 테스트 결과는 이것이 더 나은 확장 성을 의미합니다.
Jack Douglas

2
나는 심볼릭 링크 시도 /dev/urandom/var/lib/pgsql/data와 함께 읽기 pg_read_file()미친 포인트를 보너스,하지만 불행히도 pg_read_file()읽고 text는 BYTEA을 읽을 수 있도록 인코딩 변환을 통해 입력합니다. 당신이 정말로 최대 속도를 원하는 경우 쓰기 C바이너리 데이터를 생성하고 :-) 버퍼 주위에 bytea와 데이텀 포장 빠른 의사 난수 생성기를 사용하는 확장 기능
크레이그 벨소리

1
@JackDouglas 나는 그것을 도울 수 없었다. 의 C 확장 버전 random_bytea. github.com/ringerc/scrapcode/tree/master/postgresql/…
Craig Ringer

1
또 다른 훌륭한 답변! 실제로 내가 지금까지 본 것 중 최고 중 하나입니다. 확장 프로그램을 테스트하지는 않았지만 광고 확장이 제대로 작동한다고 믿습니다.
Erwin Brandstetter

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과 값 비싼 연결 루프를 피하기 위해 접근 방식을 향상 시켰습니다. 새로운 답변을 참조하십시오. bytea의 PL / PgSQL 연결 루프 대신 generate_series에 string_agg를 사용하면 성능이 150 배 향상됩니다.
Craig Ringer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.