Vorrei essere in grado di generare byteacampi 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 byteacampi 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 SQLfunzione semplice che è più economica da chiamare rispetto a PL / PgSQL.
La differenza di prestazioni dovuta al metodo di aggregazione modificato è immensa per byteavalori 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/urandomin /var/lib/pgsql/datae la lettura con pg_read_file()per il bonus punti pazzeschi, ma purtroppo pg_read_file()recita textingresso tramite una conversione di codifica, quindi non in grado di leggere bytea. Se vuoi davvero la massima velocità, scrivi una Cfunzione 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