Vorrei essere in grado di generare bytea
campi casuali di lunghezza arbitraria (<1 Gb) per popolare i dati dei test.
Qual è il modo migliore per fare questo?
Vorrei essere in grado di generare bytea
campi casuali di lunghezza arbitraria (<1 Gb) per popolare i dati dei test.
Qual è il modo migliore per fare questo?
Risposte:
Migliorando la risposta di Jack Douglas per evitare la necessità di loop PL / PgSQL e di concatenare bytea, puoi usare:
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';
È una SQL
funzione semplice che è più economica da chiamare rispetto a PL / PgSQL.
La differenza di prestazioni dovuta al metodo di aggregazione modificato è immensa per bytea
valori più grandi . Sebbene la funzione originale sia in realtà fino a 3 volte più veloce per dimensioni <50 byte, questa scala è molto meglio per valori più grandi.
Oppure usa una funzione di estensione C :
Ho implementato un generatore bytea casuale come una semplice funzione di estensione C. È nel mio repository scrapcode su GitHub . Vedi il README lì.
Colpisce le prestazioni della versione SQL sopra:
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
FROM generate_series(0, $1);
debba essere FROM generate_series(1, $1);
. Hai provato la ricorsione? Il mio test limitato implica che questo ridimensiona meglio:
/dev/urandom
in /var/lib/pgsql/data
e la lettura con pg_read_file()
per il bonus punti pazzeschi, ma purtroppo pg_read_file()
recita text
ingresso tramite una conversione di codifica, quindi non in grado di leggere bytea. Se vuoi davvero la massima velocità, scrivi una C
funzione di estensione che utilizza un generatore di numeri pseudo-casuale veloce per produrre dati binari e avvolgere un dato bytea attorno al buffer :-)
random_bytea
. github.com/ringerc/scrapcode/tree/master/postgresql/…
Vorrei essere in grado di generare casualmente bytea campi di lunghezza arbitraria
Questa funzione lo farà, ma 1 Gb richiederà molto tempo perché non si ridimensiona linearmente con la lunghezza dell'uscita:
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;$$;
test di uscita:
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 qui