मैं एक यादृच्छिक बाइट कैसे उत्पन्न कर सकता हूं


18

मैं byteaपरीक्षण डेटा को आबाद करने के लिए मनमानी लंबाई (<1Gb) के यादृच्छिक क्षेत्र उत्पन्न करने में सक्षम होना चाहूंगा ।

ऐसा करने का सबसे अच्छा तरीका क्या है?

जवाबों:


20

पीएल / पीजीक्यूएल लूपिंग और बाइटिया कॉन्टेनेशन की आवश्यकता से बचने के लिए जैक डगलस का जवाब बढ़ा सकते हैं, आप यह कर सकते हैं:

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मूल्यों के लिए अपार है । हालांकि मूल फ़ंक्शन वास्तव में आकार <3x बाइट्स के लिए 3x तेज है, यह एक बड़े मूल्यों के लिए बहुत बेहतर है।

या C एक्सटेंशन फ़ंक्शन का उपयोग करें :

मैंने एक साधारण C एक्सटेंशन फ़ंक्शन के रूप में एक यादृच्छिक बाइटा जनरेटर लागू किया है। यह GitHub पर मेरे स्क्रैपकोड रिपॉजिटरी में है । वहां 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
खैर, मैं लगभग एक ही समाधान के साथ आया था, लेकिन केवल निचले मूल्यों के लिए परीक्षण किया गया था। वहाँ @ जैक का समाधान स्पष्ट विजेता था। आपके लिए यहां नहीं रुकने के लिए +1 :)
dezso

धन्यवाद - यह उत्कृष्ट और विचार उत्तेजक है। मुझे लगता FROM generate_series(0, $1);है कि होना चाहिए FROM generate_series(1, $1);। क्या आपने पुनरावर्तन की कोशिश की है? मेरे सीमित परीक्षण का तात्पर्य है कि यह तराजू बेहतर है:
जैक डगलस

2
मैंने बोनस क्रेजी पॉइंट्स के साथ इसे पढ़ने और इसे पढ़ने /dev/urandomमें सहानुभूति रखने की कोशिश की , लेकिन दुर्भाग्य से एन्कोडिंग रूपांतरण के माध्यम से इनपुट को पढ़ता है , इसलिए यह पेटी को नहीं पढ़ सकता है। यदि आप वास्तव में अधिकतम गति चाहते हैं, तो एक विस्तार फ़ंक्शन लिखें जो बाइनरी डेटा का उत्पादन करने के लिए एक तेज़ छद्म-यादृच्छिक संख्या जनरेटर का उपयोग करता है और बफ़र के चारों ओर बाइटी डेटम लपेटता है:/var/lib/pgsql/datapg_read_file()pg_read_file()textC
क्रेग रिंगर

1
@JackDouglas मैं इसकी मदद नहीं कर सकता। का C विस्तार संस्करण random_byteagithub.com/ringerc/scrapcode/tree/master/postgresql/…
क्रेग रिंगर

1
एक और बेहतरीन जवाब! वास्तव में मैंने अब तक जो सर्वश्रेष्ठ देखे हैं उनमें से एक है। मैंने एक्सटेंशन का परीक्षण नहीं किया है, लेकिन मुझे विश्वास है कि यह विज्ञापन के रूप में काम करता है।
इरविन ब्रान्डसेट्टर

5

मैं मनमाने ढंग से लंबाई के यादृच्छिक बाइटा क्षेत्र उत्पन्न करने में सक्षम होना चाहूंगा

यह फ़ंक्शन करेगा, लेकिन 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 का अच्छा उपयोग। हैंडी।
क्रेग रिंगर

1
मैंने पीएल / पीजीएसक्यूएल और महंगे कंफर्टेशन लूप से बचने के लिए आपका दृष्टिकोण बढ़ाया है; नया जवाब देखें। Bytea पर पीएल / PgSQL संघनक लूप के बजाय string_agg को Gener_series का उपयोग करके मैं प्रदर्शन में 150-गुना सुधार देख रहा हूं।
क्रेग रिंगर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.