2009-05-20 10 views
5

मेरे पास एक SQL सर्वर 2005 डेटाबेस में एक तालिका है जिसका उपयोग बहुत अधिक किया जाता है। यह हमारे उत्पाद हाथ उपलब्धता की जानकारी पर है। हमें अपने गोदाम से हर घंटे अपडेट मिलते हैं और पिछले कुछ सालों से हम एक दिनचर्या चला रहे हैं जो तालिका को छोटा करता है और जानकारी अपडेट करता है। इसमें केवल कुछ सेकंड लगते हैं और अब तक कोई समस्या नहीं हुई है। हमारे पास हमारे सिस्टम का उपयोग करने वाले बहुत से लोग हैं जो अब इस जानकारी से पूछताछ करते हैं, और नतीजतन हम अवरुद्ध प्रक्रियाओं के कारण बहुत सारे टाइमआउट देख रहे हैं।टेबल को लॉक किए बिना उपयोग में होने पर तालिका में डेटा अपडेट करने का सबसे अच्छा तरीका क्या है?

... इसलिए ...

हम अपने विकल्पों पर शोध किया और समस्या को कम करने के लिए एक विचार के साथ आए हैं।

  1. हम दो तालिकाओं के लिए होगा। तालिका ए (सक्रिय) और तालिका बी (निष्क्रिय)।
  2. हम एक दृश्य तैयार करेंगे जो सक्रिय तालिका (तालिका ए) को इंगित करता है।
  3. इस टेबल की जानकारी (4 ऑब्जेक्ट्स) की सभी चीजों को अब दृश्य के माध्यम से जाना होगा।
  4. प्रति घंटा दिनचर्या निष्क्रिय तालिका को छोटा कर देगा, इसे नवीनतम जानकारी के साथ अद्यतन करें, फिर निष्क्रिय तालिका पर इंगित करने के लिए दृश्य को अपडेट करें, इसे सक्रिय बनाएं।
  5. यह दिनचर्या निर्धारित करेगा कि कौन सी तालिका सक्रिय है और मूल रूप से उनके बीच दृश्य को स्विच करें।

इसमें क्या गलत है? दृश्य मध्य क्वेरी को समस्याएं बदलना समस्याएं पैदा करेगा? क्या यह काम कर सकता है?

आपकी विशेषज्ञता के लिए धन्यवाद।

अतिरिक्त सूचना

  • दिनचर्या एक SSIS पैकेज कई कदम peforms है और अंत में/प्रश्न में तालिका अद्यतन करता ट्रंकेटस

  • अवरुद्ध प्रक्रियाओं दो अन्य संग्रहित प्रक्रियाओं है कि इस क्वेरी हैं तालिका।

+0

अगर आप लाइसेंस है, दो अलग-अलग भार संतुलित सर्वर एक सहज विकल्प प्रदान कर सकता है। आप एक रहते हैं और दूसरे को अपडेट करते हैं और फिर स्विच करते हैं। –

उत्तर

6

क्या आपने snapshot isolation का उपयोग करने पर विचार किया है। यह आपको अपने एसएसआईएस सामान के लिए एक बड़ा वसा लेनदेन शुरू करने की अनुमति देगा और अभी भी तालिका से पढ़ा जाएगा।

यह समाधान टेबल को स्विच करने से कहीं अधिक साफ दिखता है।

+0

+1। यह वही है जो आपको करना चाहिए। आदर्श रूप में, आपको ऐसे अपडेट मिलेंगे जिन्हें सबकुछ डंप करने की आवश्यकता नहीं है, लेकिन जब से आप नहीं करते हैं, तो चाल एक लेनदेन शुरू करना है, सबकुछ हटाएं (छेड़छाड़ नहीं करें), फिर सबकुछ लोड करें। तत्काल जो आप प्रतिबद्ध करते हैं, डेटाबेस किसी भी अंतर के साथ सबकुछ बदल देगा। –

+0

क्यों छंटनी नहीं है? क्या हर डिलीट लॉग होने के बाद इसे हटाना धीमा नहीं होगा? –

+0

मुझे लगता है कि यह मुद्दा है। स्नैपशॉट अलगाव का उपयोग करके, यह प्रतिबद्धता है जो उपयोगकर्ताओं को नया डेटा देखने का कारण बनती है। truncate लॉग इन नहीं है और मुझे नहीं पता कि यह ट्रांजैक्टन को कैसे प्रभावित करेगा लेकिन शायद यह नहीं कि आप कैसे चाहते हैं। असल में मैं शर्त लगाता हूं कि तालिका में लंबित लेनदेन होने पर छंटनी विफल हो जाएगी। – Zack

2

मुझे लगता है कि यह इसके बारे में गलत रास्ते पर जा रहा है - अद्यतन करने एक मेज यह लॉक करने के लिए है, यद्यपि आप सीमित कर सकते हैं कि प्रति पृष्ठ या यहाँ तक कि प्रति पंक्ति को ताला लगा।

मैं तालिका को छोटा नहीं कर रहा हूं और इसे फिर से भरना नहीं चाहता हूं। यह हमेशा इसे पढ़ने की कोशिश कर रहे उपयोगकर्ताओं के साथ हस्तक्षेप करने जा रहा है।

आप अद्यतन किया बजाय तालिका आप इस दूसरे रास्ते को नियंत्रित कर सकता है की जगह है - पढ़ने उपयोगकर्ताओं तालिका अवरोधित नहीं होनी चाहिए और दूर होने की आशावादी पढ़ता के साथ कर सकता है।

एसक्यूएल व्यू कथन पढ़ने के साथ (नोलॉक) संकेत जोड़ने का प्रयास करें। आपको नियमित रूप से अद्यतन होने वाली तालिका के साथ भी पढ़ने वाले उपयोगकर्ताओं की बहुत बड़ी मात्रा प्राप्त करने में सक्षम होना चाहिए।

+0

यह मेरी समझ है कि एसक्यूएल संकेत, विशेष रूप से NOLOCK कई कारणों से खराब हैं। http://tinyurl.com/qwloxh –

+1

वे लॉकिंग से बचने के लिए डेटा की प्रतियां बनाने और विचारों के पुनर्निर्माण के रूप में कहीं भी 'खराब' के करीब नहीं हैं। लॉकिंग सेट करने का सबसे अच्छा तरीका वास्तव में लेनदेन गुणों में है, लेकिन यह संभव नहीं है क्योंकि आप कटाई का उपयोग कर रहे हैं। इसके अलावा मैं उस आलेख में किए गए अंकों से असहमत हूं - कभी-कभी एसक्यूएल संकेत डेडलॉक्स से निपटने का सबसे अच्छा तरीका है, लेकिन आपको समझना होगा कि आप उनके साथ क्या कर रहे हैं। – Keith

+0

ओह, और एसओ यह करता है: http://www.codinghorror.com/blog/archives/001166.html – Keith

1

ट्रंकेट ऑपरेशन की बजाय जानकारी को अपडेट करने के लिए लेनदेन का उपयोग क्यों न करें।

ट्रंकेट लॉग नहीं है इसलिए यह लेनदेन में नहीं किया जा सकता है।

यदि आप लेनदेन में ऑपरेशन कर रहे हैं तो मौजूदा उपयोगकर्ता प्रभावित नहीं होंगे।

यह कैसे किया जाता है यह तालिका के आकार और डेटा को मूल रूप से कैसे बदलता है, इस पर निर्भर करता है। यदि आप अधिक जानकारी देते हैं तो शायद मैं आगे सलाह दे सकता हूं।

+0

रूटीन एक एसएसआईएस पैकेज है और ऐसा लगता है कि पूरी चीज एक लेनदेन में चल रही है, जो अवरोध का कारण बनती है। –

2

व्यक्तिगत रूप से, यदि आप हमेशा तालिका के खिलाफ बैच प्रक्रिया चलाने के लिए समय कम करने जा रहे हैं, तो मुझे लगता है कि आपको व्यवसाय/डेटा एक्सेस परत पर उपयोगकर्ता अनुभव का प्रबंधन करना चाहिए। एक तालिका प्रबंधन ऑब्जेक्ट का परिचय दें जो उस तालिका से कनेक्शन पर नज़र रखता है और बैच प्रोसेसिंग को नियंत्रित करता है।

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

मेरे $ 0.02,

नैट

+0

हमने इसे माना है और हमें वास्तव में यह विकल्प पसंद है, लेकिन इसे जाने के लिए बहुत अधिक काम की आवश्यकता है, और समय एक लक्जरी है जिसे दुर्भाग्य से नहीं है। लेकिन मैं इस बात पर सहमत हूं कि सर्वर बैच प्रक्रिया इष्टतम है। –

0

हम अपने उच्च उपयोग सिस्टम पर ऐसा करते हैं और किसी भी समस्या नहीं है। हालांकि, सभी चीजों के डेटाबेस के साथ, सुनिश्चित करने का एकमात्र तरीका यह मदद करेगा कि देव में परिवर्तन करना होगा और फिर परीक्षण लोड करना होगा। यह नहीं जानना कि आपका एसएसआईएस पैकेज करता है, यह अभी भी ब्लॉक का कारण बन सकता है।

1

एक संभावित समाधान तालिका को अद्यतन करने के लिए आवश्यक समय को कम करना होगा।

मैं पहले वेयरहाउस से डेटा डाउनलोड करने के लिए एक स्टेजिंग टेबल तैयार करूंगा।

आपको क्या करना है "आवेषण, अद्यतन और हटाता है" अगर अंतिम तालिका

में चलें लगता समापन समारोह टेबल इस तरह दिखता है:

Table Products: 
    ProductId  int 
    QuantityOnHand Int 

और तुम गोदाम से QuantityOnHand अपडेट करना होगा।

पहले की तरह एक स्टेजिंग तालिका बनाएँ:

Table Prodcuts_WareHouse 
    ProductId  int 
    QuantityOnHand Int 

और फिर इस तरह की एक "कार्रवाई" टेबल बनाएं:

:

Table Prodcuts_Actions 
    ProductId  int 
    QuantityOnHand Int 
    Action   Char(1) 

अद्यतन प्रक्रिया तो कुछ इस तरह होना चाहिए 1. टर्नकेट टेबल Prodcuts_WareHouse

2. टर्नकेट तालिका Prodcuts_Actions

3.Fill गोदाम

4 से डेटा के साथ Prodcuts_WareHouse तालिका।इस के साथ Prodcuts_Actions तालिका भरें:

आवेषण:

INSERT INTO Prodcuts_Actions (ProductId, QuantityOnHand,Action) 
SELECT  SRC.ProductId, SRC.QuantityOnHand, 'I' AS ACTION 
FROM   Prodcuts_WareHouse AS SRC LEFT OUTER JOIN 
         Products AS DEST ON SRC.ProductId = DEST.ProductId 
WHERE  (DEST.ProductId IS NULL) 

हटाता

INSERT INTO Prodcuts_Actions (ProductId, QuantityOnHand,Action) 
SELECT  DEST.ProductId, DEST.QuantityOnHand, 'D' AS Action 
FROM   Prodcuts_WareHouse AS SRC RIGHT OUTER JOIN 
         Products AS DEST ON SRC.ProductId = DEST.ProductId 
WHERE  (SRC.ProductId IS NULL) 

अपडेट

INSERT INTO Prodcuts_Actions (ProductId, QuantityOnHand,Action) 
SELECT  SRC.ProductId, SRC.QuantityOnHand, 'U' AS Action 
FROM   Prodcuts_WareHouse AS SRC INNER JOIN 
         Products AS DEST ON SRC.ProductId = DEST.ProductId AND SRC.QuantityOnHand <> DEST.QuantityOnHand 

अब आप बंद नहीं किया है अंतिम तालिका तक।

5.In एक सौदे अंतिम तालिका अद्यतन:

BEGIN TRANS 

DELETE Products FROM Products INNER JOIN 
Prodcuts_Actions ON Products.ProductId = Prodcuts_Actions.ProductId 
WHERE  (Prodcuts_Actions.Action = 'D') 

INSERT INTO Prodcuts (ProductId, QuantityOnHand) 
SELECT ProductId, QuantityOnHand FROM Prodcuts_Actions WHERE Action ='I'; 

UPDATE Products SET QuantityOnHand = SRC.QuantityOnHand 
FROM   Products INNER JOIN 
Prodcuts_Actions AS SRC ON Products.ProductId = SRC.ProductId 
WHERE  (SRC.Action = 'U') 

COMMIT TRAN 
ऊपर सभी प्रक्रिया के साथ

, आप कम से कम करने के लिए अद्यतन किया जा करने के लिए आवश्यक अभिलेखों की मात्रा को कम, और इतने समय अंतिम तालिका हो जाएगा अपडेट करते समय लॉक किया गया।

आप अंतिम चरण में लेनदेन का उपयोग भी नहीं कर सकते हैं, इसलिए आदेश के बीच तालिका जारी की जाएगी।

1

यदि आपके पास अपने सर्वर पर SQL सर्वर का एंटरप्राइज़ संस्करण है तो क्या मैं सुझाव दे सकता हूं कि आप SQL सर्वर विभाजन तकनीक का उपयोग करें।

आप वर्तमान में आवश्यक डेटा 'लाइव' विभाजन और 'माध्यमिक' विभाजन में डेटा के अद्यतन संस्करण (जो पूछताछ के लिए उपलब्ध नहीं है बल्कि डेटा प्रशासित करने के लिए उपलब्ध है) के भीतर रह सकता है।

एक बार डेटा 'माध्यमिक' संक्रमण में आयात किया गया है, तो आप तत्काल 'लाइव' विभाजन को स्विच कर सकते हैं और 'माध्यमिक' विभाजन में, जिससे शून्य डाउनटाइम और कोई अवरोध नहीं हो सकता है।

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

प्रत्येक बार जब आपको एक आयात नौकरी करने की आवश्यकता होती है, तो आप बस प्रक्रिया को दोहराएं/उलट दें।

एसक्यूएल सर्वर विभाजन के बारे में अधिक जानने के लिए देखें:

http://msdn.microsoft.com/en-us/library/ms345146(SQL.90).aspx

या आप बस मुझे :-)

संपादित पूछ सकते हैं:

एक तरफ ध्यान दें पर, क्रम में किसी भी अवरुद्ध मुद्दों को हल करने के लिए, आप SQL सर्वर पंक्ति संस्करण तकनीक का उपयोग कर सकते हैं।

http://msdn.microsoft.com/en-us/library/ms345124(SQL.90).aspx

+0

यह विचार है कि हम एक दृश्य के साथ क्या हासिल करना चाहते थे, लेकिन हमारे पास केवल SQL सर्वर का मानक संस्करण है। इस पर –

2

बस आप SSIS

उपयोग कर रहे हैं पढ़ने के

आप से TableDiference घटक इस्तेमाल कर सकते हैं: http://www.sqlbi.eu/Home/tabid/36/ctl/Details/mid/374/ItemID/0/Default.aspx

alt text http://www.sqlbi.eu/Portals/0/Articles/Table%20Difference%20Images/DataFlowSimple.png

इस तरह से आप एक-एक करके तालिका में परिवर्तन लागू कर सकते हैं एक लेकिन निश्चित रूप से, यह बहुत धीमा होगा और तालिका के आकार के आधार पर सर्वर पर अधिक रैम की आवश्यकता होगी, लेकिन लॉकिंग समस्या पूरी तरह से ठीक हो जाएगी।

0

यदि तालिका बहुत बड़ी नहीं है तो आप अपने आवेदन में थोड़े समय के लिए डेटा कैश कर सकते हैं। यह पूरी तरह से अवरुद्ध करने को समाप्त नहीं कर सकता है, लेकिन यह संभावना कम हो जाएगी कि अद्यतन होने पर तालिका की पूछताछ की जाएगी।

0

शायद उन प्रक्रियाओं के कुछ विश्लेषण करना समझदारी होगी जो अवरुद्ध हो रहे हैं क्योंकि वे आपके परिदृश्य का हिस्सा हैं जो बदल गए हैं। यह आपके द्वारा देखे जा रहे ब्लॉक बनाने के लिए केवल एक खराब लिखित क्वेरी लेता है। खराब लिखित क्वेरी को छोड़कर, शायद तालिका को उन प्रश्नों को तेज़ी से बढ़ाने के लिए एक या अधिक कवर इंडेक्स की आवश्यकता होती है और आपके पहले से ही काम करने वाले कोड को फिर से इंजीनियर किए बिना आपको अपने रास्ते पर वापस ले जाती है।

आशा इस मदद करता है,

विधेयक

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

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