2010-02-01 16 views
33

के रूप में डेटाबेस तालिका का उपयोग करना मैं एक कतार के रूप में डेटाबेस तालिका का उपयोग करना चाहता हूं। मैं इसमें सम्मिलित करना चाहता हूं और इसमें से सम्मिलित क्रम (एफआईएफओ) में तत्व लेना चाहता हूं। मेरा मुख्य विचार प्रदर्शन है क्योंकि मेरे पास प्रत्येक सेकेंड में इनमें से हजार लेनदेन हैं। तो मैं एक एसक्यूएल क्वेरी का उपयोग करना चाहता हूं जो मुझे पूरी तालिका को खोजे बिना पहला तत्व देता है। जब मैं इसे पढ़ता हूं तो मैं एक पंक्ति को नहीं हटाता हूं। शीर्ष 1 चुनें ..... यहां सहायता करें? क्या मुझे किसी विशेष इंडेक्स का उपयोग करना चाहिए?एक कतार

+1

के लिए इस देखें कैसे एसक्यूएल सर्वर में एक कतार लागू करने के लिए का अच्छा वर्णन के लिए यह लेख देखें: http://www.mssqltips.com/sqlservertip/1257/processing-data-queues-in -एसक्ल-सर्वर-साथ-रीडपैस्ट-एंड-अपडेटलॉक/ –

+0

पंक्ति-आधारित तर्क का उपयोग करते हुए जैसे SQL सर्वर में कतार को प्रोसेस करना संसाधनों का एक बड़ा दुरुपयोग है .. सेट-आधारित तर्क –

उत्तर

23

मैं प्रत्येक पंक्तिबद्ध आइटम के लिए विशिष्ट रूप से वृद्धि आईडी प्रदान करने के लिए प्राथमिक कुंजी के रूप में एक पहचान क्षेत्र का उपयोग करता हूं, और उस पर एक क्लस्टर इंडेक्स चिपकाता हूं। यह उस क्रम का प्रतिनिधित्व करेगा जिसमें वस्तुओं को कतारबद्ध किया गया था।

जब आप उन्हें संसाधित करते हैं तो आइटम को कतार तालिका में रखने के लिए, आपको किसी विशेष आइटम की वर्तमान स्थिति इंगित करने के लिए "स्थिति" फ़ील्ड की आवश्यकता होगी (उदाहरण के लिए 0 = प्रतीक्षा, 1 = संसाधित किया जा रहा है, 2 = संसाधित) । किसी आइटम को दो बार संसाधित करने से रोकने के लिए इसकी आवश्यकता होती है।

कतार में वस्तुओं को संसाधित करते समय, आपको तालिका में अगला आइटम ढूंढना होगा, वर्तमान में संसाधित नहीं किया जा रहा है। इसे इस तरह से होने की आवश्यकता होगी ताकि एक ही आइटम को एक ही समय में प्रदर्शित करने के लिए कई प्रक्रियाओं को रोकने के लिए नीचे दिखाया जा सके। table hints UPDLOCK और READPAST पर ध्यान दें जिन्हें आपको कतार लागू करने के बारे में पता होना चाहिए।

उदा। एक स्पोक के भीतर, इस तरह कुछ:

DECLARE @NextID INTEGER 

BEGIN TRANSACTION 

-- Find the next queued item that is waiting to be processed 
SELECT TOP 1 @NextID = ID 
FROM MyQueueTable WITH (UPDLOCK, READPAST) 
WHERE StateField = 0 
ORDER BY ID ASC 

-- if we've found one, mark it as being processed 
IF @NextId IS NOT NULL 
    UPDATE MyQueueTable SET Status = 1 WHERE ID = @NextId 

COMMIT TRANSACTION 

-- If we've got an item from the queue, return to whatever is going to process it 
IF @NextId IS NOT NULL 
    SELECT * FROM MyQueueTable WHERE ID = @NextID 

यदि कोई आइटम संसाधित करने में विफल रहता है, तो क्या आप इसे बाद में पुनः प्रयास करने में सक्षम होना चाहते हैं? यदि ऐसा है, तो आपको या तो स्थिति को 0 या कुछ पर रीसेट करने की आवश्यकता होगी। इसके लिए और विचार की आवश्यकता होगी।

वैकल्पिक रूप से, डेटाबेस तालिका को कतार के रूप में उपयोग न करें, लेकिन एमएसएमक्यू की तरह कुछ - बस सोचा कि मैं इसे मिश्रण में फेंक दूंगा!

+0

मुझे चुनिंदा आईडी से चयन आईडी को अलग क्यों करना चाहिए? – Shayan

+0

आपको ऐसा करने की ज़रूरत नहीं है, आप पहले वैल्यू के रूप में एक ही समय में वैरिएबल में आवश्यक सभी मान लोड कर सकते हैं, और फिर अंत में उन्हें वापस कर सकते हैं। इसके अलावा, मैंने सादगी के लिए "चयन *" किया है - केवल उन फ़ील्ड को वापस लौटें जिन्हें आपको वास्तव में चाहिए। – AdaTheDev

+0

मैं प्रोग्राम के विभिन्न हिस्सों के लॉकिंग प्रभाव को कम करने के लिए इस तालिका में विदेशी कुंजी के साथ प्रक्रिया तालिका को एक अलग तालिका में रखना चाहता हूं। क्या यह विधि मदद करता है? इसके लिए मुझे किस प्रकार की अनुक्रमणिका का उपयोग करना चाहिए? – Shayan

4

सब कुछ आपके डेटाबेस इंजन/कार्यान्वयन पर निर्भर करता है।

मेरे लिए निम्नलिखित कॉलम के साथ टेबल पर सरल कतार:

id/task/priority/date_added 

आमतौर पर काम करता है।

मैंने समूह कार्यों को प्राथमिकता और कार्य का उपयोग किया और दोगुनी कार्य के मामले में मैंने इसे बड़ी प्राथमिकता के साथ चुना।

और चिंता न करें - आधुनिक डेटाबेस के लिए "हजारों" कुछ खास नहीं है।

+0

के लिए एसक्यूएल का उपयोग करें ये क्या हैं? मैं SQL सर्वर 2008 का उपयोग करता हूं। – Shayan

+0

मुझे लगता है कि आप "टेबल" ऊपर दिए गए स्थानों में से एक में "इंडेक्स" का मतलब है (मैं इसे ठीक कर दूंगा, लेकिन मैं * 100% * निश्चित नहीं हूं कि कौन सा टाइपो है)। –

+0

क्षमा करें, मेरे मामले में सभी कॉलम पर "कॉलम" – bluszcz

7

यदि आप अपनी संसाधित पंक्तियों को नहीं हटाते हैं, तो आपको किसी प्रकार के ध्वज की आवश्यकता होगी जो इंगित करता है कि एक पंक्ति पहले ही संसाधित हो चुकी है।

उस ध्वज पर एक सूचकांक डालें, और उस कॉलम पर जिसे आप ऑर्डर करने जा रहे हैं।

उस झंडे पर अपनी तालिका को विभाजित करें, इसलिए अस्वीकृत लेनदेन आपके प्रश्नों को छेड़छाड़ नहीं कर रहे हैं।

यदि आपको वास्तव में 1.000 संदेश हर सेकेंड मिलेंगे, तो परिणामस्वरूप 86.400.000 पंक्तियां एक दिन होगी। आप पुरानी पंक्तियों को साफ करने के किसी तरीके के बारे में सोचना चाह सकते हैं।

+0

ध्वज क्या है? – Shayan

+0

'ध्वज'' से मेरा मतलब है कि कुछ कॉलम याद रखें, अगर आपके क्लाइंट द्वारा एक पंक्ति पहले ही संसाधित हो चुकी है। –

+0

मेरा मानना ​​है कि उनका मतलब था कि आप अपनी टेबल पर एक कॉलम जोड़ सकते हैं - शायद अस्वीकृत - जो प्रत्येक लेनदेन की स्थिति रखेगा।चूंकि आप उन्हें हटाने के बाद पंक्तियों को हटा नहीं रहे हैं, इसलिए आपको यह जानने का एक तरीका होना चाहिए कि कौन से लेन-देन को अनदेखा करना है। आप इसे थोड़ा सा क्षेत्र बना सकते हैं, 0 कतार के लिए 0 और डेक्यूड के लिए 1। –

2

शायद अपने चुनिंदा बयान में मदद मिलेगी की एक सीमा होती = 1 जोड़ रहा है ... एक भी मैच के बाद वापसी ...

+0

टॉप 1 के साथ क्या अंतर है? – Shayan

+0

मुझे पता है कि SQL सर्वर शीर्ष 1 का उपयोग कर सकता है पोस्टग्रेज़ में LIMIT 1 जैसा ही है। मुझे कल्पना है कि अन्य सभी विक्रेता एक या दूसरे को स्वीकार करेंगे। – Matt

+1

मैं ईमानदार रहूंगा, मुझे एहसास नहीं हुआ कि वे एक ही चीज़ के बराबर थे ... मैंने कभी भी शीर्ष वाक्यविन्यास का उपयोग नहीं किया है, केवल LIMIT ... यही कारण है कि मैं स्टैक ओवरफ्लो से प्यार करता हूं: यहां तक ​​कि एक उत्तर देने में भी, मैं कुछ नया सीखता हूँ। –

2

एक तारीख (या autoincrement) स्तंभ पर एक क्लस्टर सूचकांक बनाएं मजबूर। यह सूचकांक क्रम में मोटे तौर पर तालिका में पंक्तियों को रखेगा और जब आप ORDER BY अनुक्रमित कॉलम पर तेजी से इंडेक्स-आधारित पहुंच की अनुमति देंगे। TOP X (या LIMIT X का उपयोग करके, अपने आरडीएमबीएस के आधार पर) केवल सूचकांक से पहले एक्स आइटम पुनर्प्राप्त करेगा।

प्रदर्शन चेतावनी: ऑप्टिमाइज़र अप्रत्याशित चीजें नहीं करता है, यह सत्यापित करने के लिए आपको हमेशा अपने प्रश्नों (वास्तविक डेटा पर) की निष्पादन योजनाओं की समीक्षा करनी चाहिए। सूचित निर्णय लेने में सक्षम होने के लिए अपने प्रश्नों (फिर से वास्तविक डेटा पर) बेंचमार्क करने का प्रयास करें।

2

जब तक आप डालने के समय के ट्रैक को ट्रैक रखने के लिए कुछ उपयोग करते हैं, तब तक यह कोई परेशानी नहीं होगी। mysql options के लिए यहां देखें। सवाल यह है कि क्या आपको केवल सबसे हाल ही में सबमिट की गई वस्तु की आवश्यकता है या फिर आपको फिर से शुरू करने की आवश्यकता है या नहीं। यदि आपको पुन: प्रयास करने की आवश्यकता है, तो आपको ORDER BY कथन, लूप के माध्यम से, और को अंतिम डेटाटाइम याद रखने के लिए क्या करना है ताकि आप अपना अगला हिस्सा पकड़ सकें।

2

चूंकि आप तालिका से रिकॉर्ड नहीं हटाते हैं, इसलिए आपको (processed, id) पर एक समग्र अनुक्रमणिका होना चाहिए, जहां processed वह कॉलम है जो इंगित करता है कि वर्तमान रिकॉर्ड संसाधित किया गया था या नहीं।

सबसे अच्छी बात आपके रिकॉर्ड के लिए विभाजित तालिका तैयार करेगी और PROCESSED विभाजन कुंजी को फ़ील्ड करेगी। इस तरह, आप तीन या अधिक स्थानीय इंडेक्स रख सकते हैं।

हालांकि, अगर आप हमेशा id क्रम में रिकॉर्ड केवल दो राज्यों की प्रक्रिया है, और है, रिकॉर्ड को अपडेट करने का मतलब होगा सिर्फ सूचकांक की पहली पत्ती से रिकॉर्ड लेने और पिछले पत्ती

करने के लिए इसे जोड़कर वर्तमान में संसाधित रिकॉर्ड में सभी अप्रत्याशित रिकॉर्ड्स के कम से कम id और सभी संसाधित रिकॉर्ड्स के सबसे बड़े id होंगे।

+0

मैं प्रोग्राम के विभिन्न हिस्सों के लॉकिंग प्रभाव को कम करने के लिए इस तालिका में विदेशी कुंजी के साथ प्रक्रिया तालिका को एक अलग तालिका में रखना चाहता हूं। – Shayan

+4

'@ शायन': इससे आपके चयन प्रदर्शन पर गंभीर प्रभाव पड़ेगा। और वैसे भी प्रसंस्करण करते समय आपको फ़ील्ड को लॉक करने की आवश्यकता है। – Quassnoi

0

लेनदेन नहीं होने के लिए इसके लिए एक बहुत ही आसान समाधान, ताले आदि परिवर्तन ट्रैकिंग तंत्र (डेटा कैप्चर नहीं) का उपयोग करना है। यह प्रत्येक जोड़ा/अपडेट/हटाई गई पंक्ति के लिए वर्जनिंग का उपयोग करता है ताकि आप ट्रैक कर सकें कि किसी विशिष्ट संस्करण के बाद क्या परिवर्तन हुआ।

तो, आप अंतिम संस्करण जारी रखते हैं और नए परिवर्तनों की क्वेरी करते हैं।

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

उदाहरण Using Change Tracking in SQL Server 2008

+0

परिवर्तन ट्रैकिंग कैसे आपको डेटाबेस तालिका का उपयोग कतार के रूप में करने में मदद करती है? एक कतार में, आप अगला उपलब्ध कार्य (एफआईएफओ ऑर्डर में) प्राप्त करना चाहते हैं, जिसे पहले ही संसाधित नहीं किया गया है, और यह सुनिश्चित करें कि आइटम केवल एक बार संसाधित हो जाए। परिवर्तन ट्रैकिंग पूरी तरह से अलग समस्या हल करती है - आखिरी पूछताछ के बाद से तालिका की कौन सी पंक्तियां बदल गई हैं। मैं कनेक्शन नहीं देख रहा हूँ। –

+0

अच्छा बिंदु ब्रायन और आप सही हैं। मैंने परिवर्तन ट्रैकिंग का प्रस्ताव दिया ताकि टेबल कतारों की आवश्यकता नहीं होगी। वह मेरा मुद्दा था। कतार भरने के लिए ट्रिगर्स (संभवतः) या कुछ और का उपयोग करने के बजाय, कोई भी स्रोत तालिकाओं से परिवर्तन प्राप्त करने के लिए परिवर्तन ट्रैकिंग तंत्र का उपयोग कर सकता है, जब तक कि वह परिवर्तनों को ट्रैक करना चाहता है ..... टिप्पणी के लिए धन्यवाद। –

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