2010-02-23 9 views
5

ठीक है,100k पंक्तियाँ, एक यादृच्छिक क्रम में वापस किया गया एक एसक्यूएल समय के बिना बाहर कृपया

मैं एक यादृच्छिक पंक्ति पिछले साल सेट लौटने पर पढ़ने का एक बहुत कुछ कर रहा हूँ, और समाधान हम साथ आया

था
ORDER BY newid() 

यह < 5k पंक्तियों के लिए ठीक है। लेकिन जब हमें मिल रहा है> 10-20k पंक्तियां हमें एसक्यूएल टाइम आउट मिल रही हैं, निष्पादन योजना ने मुझे बताया कि मेरी क्वेरी लागत का 76% इस लाइन से आता है। और जब हम बड़ी मात्रा में पंक्तियां रखते हैं तो इस रेखा को हटाने से परिमाण के क्रम से गति बढ़ जाती है।

हमारे उपयोगकर्ताओं को इस तरह के समय में 100k पंक्तियों तक करने की आवश्यकता है।

आपको कुछ और विवरण देने के लिए।

हमारे पास 2.6 मिलियन 4 अंकों अल्फा-न्यूमेरिक कोड वाली एक तालिका है। हम किसी स्थान पर प्रवेश प्राप्त करने के लिए इनमें से एक यादृच्छिक सेट का उपयोग करते हैं। उदाहरण के लिए, यदि हमारे पास 5000 क्षमता वाला कोई ईवेंट है, तो इनमें से 5000 का एक यादृच्छिक सेट तालिका से खींचा जाएगा, फिर प्रत्येक ग्राहक को बार-कोड के रूप में जारी किया जाएगा, फिर दरवाजे पर बार-कोड स्कैनिंग ऐप होगा 5000 की एक ही सूची। 4 अंकों वाले अल्फा न्यूमेरिक कोड (और एक GUID की तरह बेवकूफ लंबी संख्या नहीं) का उपयोग करने का कारण यह है कि लोगों के लिए संख्या लिखना आसान है (या किसी मित्र को एसएमएस करें) और बस इसे लाएं संख्या और इसे मैन्युअल रूप से दर्ज किया है, इसलिए हम बड़ी संख्या में वर्ण नहीं चाहते हैं। ग्राहक अंतिम बिट बीटीडब्ल्यू प्यार करते हैं।

ORDER BY newid() से बेहतर तरीका है, या 2.6 मिलियन के साथ तालिका से 100k यादृच्छिक पंक्तियां प्राप्त करने का एक तेज़ तरीका है?

ओह, और हम एमएस एसक्यूएल उपयोग कर रहे हैं 2005

धन्यवाद,

जो

+0

यहां एक दिलचस्प पढ़ा गया है: http://www.sqlteam.com/article/returning-rows-in-random-order-part-ii-revenge-of-the-randomizer –

उत्तर

3

आप यादृच्छिक 4 अंकों कोड जनरेट करना चाहते हैं, क्यों नहीं सिर्फ उन्हें उत्पन्न बजाय खींचने की कोशिश कर उन्हें डेटाबेस से बाहर?

0 से 1,679,616 से 100k अद्वितीय संख्याएं उत्पन्न करें (जो अनन्य चार अंकों वाले अल्फान्यूमेरिक कोडों की संख्या है, अनदेखी करते हुए - 2.6 मिलियन पंक्तियों में कुछ डुप्लीकेट होना चाहिए) और उन्हें अपने चार अंकों के कोड में परिवर्तित करें।

0
बस ब्याज की बात के रूप

, क्या, जैसा कि आप द्वारा

ORDER BY CHECKSUM(newid()) 
0

एक विचार

ORDER BY newid() 

की जगह प्रदर्शन चरणों में प्रक्रिया को तोड़ने की है। GUID के लिए तालिका में एक कॉलम जोड़ें, फिर GUID जोड़कर तालिका में एक अद्यतन कथन करें। यदि आवश्यक हो तो यह समय से पहले किया जा सकता है। इसके बाद आपको परिणामों को प्राप्त करने के लिए GUID कॉलम पर ऑर्डरबी के साथ क्वेरी को चलाने में सक्षम होना चाहिए।

7

वहाँ एक MSDN लेख "Selecting Rows Randomly from a Large Table" हकदार है कि इस सटीक समस्या के बारे में बात करती है और एक समाधान से पता चलता है (कोई छँटाई लेकिन बजाय एक उत्पन्न स्तंभ पर एक कहां खंड का उपयोग कर पंक्तियों को फ़िल्टर करने का उपयोग) है।

आपकी क्वेरी धीमी है कारण यह है कि ORDER BY खंड पूरे तालिका को सॉर्ट करने के लिए tempdb में कॉपी करने का कारण बनता है।

1

आपको सॉर्ट करने की आवश्यकता नहीं है।

DECLARE @RandomNumber int 
DECLARE @Threshold float 
SELECT @RandomNumber = COUNT(*) FROM customers 
SELECT @Threshold = 50000/@RandomNumber 

SELECT TOP 50000 * FROM customers WHERE rand() > @Threshold ORDER BY newid() 
+0

आप अभी भी सॉर्ट कर रहे हैं क्योंकि आपके पास ' आपकी क्वेरी में newid() 'द्वारा आदेश। – adrianbanks

+0

लेकिन मैं केवल 50k सीए क्रमबद्ध हूं, पूरी तालिका नहीं। बात यह है कि अगर हम रैंड के साथ 50k से अधिक का चयन करते हैं() हमें उन्हें छोड़ना होगा। लेकिन अगर हमने बिना छेड़छाड़ किए टॉप को लिया, तो सूची में पहले लोगों को विशेषाधिकार प्राप्त होगा। – user76035

0

क्या आपने किसी दिए गए int कॉलम पर% (modulo) का उपयोग करने का प्रयास किया है? सुनिश्चित नहीं हैं कि अपनी मेज संरचना है, लेकिन आप कुछ इस तरह कर सकता है:

your_table से चयन शीर्ष 50000 * जहां कास्ट ((कास्ट (ASCII (SUBSTRING (venuecode, 1,1)) varchar के रूप में (3)) + CAST (ASCII (सबस्ट्रिंग (स्थलकोड, 2,1)) वर्कर (3) के रूप में) + CAST (ASCII (सबस्ट्रिंग (स्थलकोड, 3,1)) वर्कर (3) के रूप में) + CAST (ASCII (सबस्ट्रिंग (स्थलकोड, 4,1)) वर्चर (3))) के रूप में) 0 और 50000

उपरोक्त कोड आपके सभी अल्फा न्यूमेरिक स्थानों को ले जाएगा और उन्हें एक पूर्णांक में परिवर्तित करेगा और फिर पूरे को विभाजित करेगा 500,000 बाल्टी में टेबल जिसमें आप शीर्ष 50000 ले रहे हैं जो 0 और 50000 के बीच आते हैं। आप पी कर सकते हैं (500,000) के बाद से% के बाद संख्या के साथ रखना और आप बीच के साथ खेल सकते हैं। यह आपके लिए यादृच्छिक होना चाहिए। सुनिश्चित नहीं है कि जहां खंड आपको प्रदर्शन पर काट देगा, लेकिन यह एक शॉट के लायक है। इसके अलावा, आदेश के बिना, आदेश की कोई गारंटी नहीं है (यदि आपके पास एकाधिक सीपीयू और थ्रेडिंग है)।

संबंधित मुद्दे