Bagaimana saya bisa menghasilkan bytea acak


18

Saya ingin dapat menghasilkan byteabidang acak dengan panjang acak (<1Gb) untuk mengisi data uji.

Apa cara terbaik untuk melakukan ini?

Jawaban:


20

Meningkatkan jawaban Jack Douglas untuk menghindari perlunya perulangan PL / PgSQL dan bytea, Anda dapat menggunakan:

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

Ini adalah SQLfungsi sederhana yang lebih murah untuk dipanggil daripada PL / PgSQL.

Perbedaan dalam kinerja karena metode agregasi yang diubah sangat besar untuk byteanilai yang lebih besar . Meskipun fungsi aslinya sebenarnya hingga 3x lebih cepat untuk ukuran <50 byte, yang satu ini jauh lebih baik untuk nilai yang lebih besar.

Atau gunakan fungsi ekstensi C :

Saya telah mengimplementasikan generator bytea acak sebagai fungsi ekstensi C sederhana. Itu ada di repositori scrapcode saya di GitHub . Lihat README di sana.

Itu nukes kinerja versi SQL di atas:

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
Yah, saya datang dengan solusi yang hampir sama, tetapi diuji hanya untuk nilai yang lebih rendah. Solusi There @ Jack adalah pemenang yang jelas. +1 untuk Anda karena tidak berhenti di sini :)
dezso

Terima kasih - ini luar biasa dan memprovokasi pemikiran. Saya pikir FROM generate_series(0, $1);perlu FROM generate_series(1, $1);. Sudahkah Anda mencoba rekursi? Pengujian terbatas saya menunjukkan bahwa skala ini lebih baik:
Jack Douglas

2
Saya mencoba menghubungkan /dev/urandomke /var/lib/pgsql/datadan membacanya dengan pg_read_file()bonus poin gila, tetapi sayangnya pg_read_file()membaca textinput melalui konversi pengkodean, sehingga tidak dapat membaca bytea. Jika Anda benar-benar menginginkan kecepatan maksimal, tulislah Cfungsi ekstensi yang menggunakan generator nomor acak pseudo-acak untuk menghasilkan data biner dan bungkus bytea datum di sekitar buffer :-)
Craig Ringer

1
@ JackDouglas saya tidak bisa menahannya. Versi ekstensi C dari random_bytea. github.com/ringerc/scrapcode/tree/master/postgresql/…
Craig Ringer

1
Jawaban bagus lainnya! Sebenarnya salah satu yang terbaik yang pernah saya lihat sejauh ini. Saya belum menguji ekstensi, tetapi saya percaya itu berfungsi seperti yang diiklankan.
Erwin Brandstetter

5

Saya ingin dapat menghasilkan bidang bytea acak yang panjangnya sewenang-wenang

Fungsi ini akan melakukannya, tetapi 1Gb akan memakan waktu lama karena tidak skala secara linear dengan panjang output:

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

tes keluaran:

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|
*/

Aku di sini


Penggunaan width_bucket yang bagus. Berguna.
Craig Ringer

1
Saya telah meningkatkan pendekatan Anda untuk menghindari PL / PgSQL dan loop concatenation mahal; lihat jawaban baru. Dengan menggunakan string_agg alih-alih menghasilkan_series alih-alih loop konkatasi PL / PgSQL pada bytea, saya melihat peningkatan kinerja 150 kali lipat.
Craig Ringer
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.