मैं SQL में एक कुशल सरल यादृच्छिक नमूना कैसे ले सकता हूँ? प्रश्न में डेटाबेस MySQL चला रहा है; मेरी तालिका कम से कम 200,000 पंक्तियाँ है, और मुझे लगभग 10,000 का एक सरल यादृच्छिक नमूना चाहिए।
"स्पष्ट" उत्तर है:
SELECT * FROM table ORDER BY RAND() LIMIT 10000
बड़ी तालिकाओं के लिए, यह बहुत धीमी है: यह RAND()
हर पंक्ति (जो पहले से ही इसे ओ (एन) पर रखती है) के लिए कॉल करती है , और उन्हें छांटती है, जिससे यह ओ (एन एलजी एन) सबसे अच्छा होता है। क्या O (n) की तुलना में इसे तेज़ करने का कोई तरीका है?
नोट : जैसा कि एंड्रयू माओ टिप्पणियों में बताते हैं, यदि आप SQL सर्वर पर इस दृष्टिकोण का उपयोग कर रहे हैं, तो आपको T-SQL फ़ंक्शन का उपयोग करना चाहिए NEWID()
, क्योंकि RAND () सभी पंक्तियों के लिए समान मान वापस कर सकता है ।
संपादित करें: 5 साल की उम्र
मैं एक बड़ी तालिका के साथ फिर से इस समस्या में भाग गया, और दो अज्ञानी लोगों के साथ @ अज्ञानी समाधान के एक संस्करण का उपयोग करके समाप्त हो गया:
- सस्ते के लिए पंक्तियों को 2-5x मेरे वांछित नमूने के आकार का नमूना दें
ORDER BY RAND()
RAND()
प्रत्येक इन्सर्ट / अपडेट पर एक अनुक्रमित कॉलम के परिणाम को सहेजें । (यदि आपका डेटा सेट बहुत अपडेट-भारी नहीं है, तो आपको इस कॉलम को नया बनाए रखने के लिए दूसरा तरीका खोजने की आवश्यकता हो सकती है।)
किसी तालिका का 1000-आइटम नमूना लेने के लिए, मैं पंक्तियों की गणना करता हूं और परिणाम को नीचे की ओर ले जाता हूं, औसतन, 10,000 पंक्तियों को जमे हुए_और कॉलम के साथ:
SELECT COUNT(*) FROM table; -- Use this to determine rand_low and rand_high
SELECT *
FROM table
WHERE frozen_rand BETWEEN %(rand_low)s AND %(rand_high)s
ORDER BY RAND() LIMIT 1000
(मेरे वास्तविक कार्यान्वयन में यह सुनिश्चित करने के लिए अधिक काम शामिल है कि मैं अंडरस्लैम नहीं करता हूं, और मैन्युअल रूप से rand_high को चारों ओर लपेटने के लिए, लेकिन मूल विचार "बेतरतीब ढंग से अपने एन को कुछ हज़ार में कटौती करना है।")
हालांकि यह कुछ बलिदान करता है, यह मुझे एक सूचकांक स्कैन का उपयोग करके डेटाबेस को नमूना करने की अनुमति देता है, जब तक कि यह ORDER BY RAND()
फिर से छोटा न हो ।
RAND()
हर बाद की कॉल पर समान मूल्य देता है।