100 मिमी रिकॉर्ड पर JOIN के साथ अपडेट करें, यह बेहतर कैसे करें? (टी-एसक्यूएल में)


11

मुझे एक तालिका में 100 मिलियन रिकॉर्ड अपडेट करने की आवश्यकता है, प्रभाव में, केवल एक आईडी के साथ एक कॉलम के वर्चर मान को बदलकर तालिका को सामान्य करना। (मैं कहता हूं "प्रतिस्थापित करना" लेकिन वास्तव में मैं आईडी को दूसरे कॉलम में लिख रहा हूं।)

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

UPDATE A
SET A.AutoClassID = B.AutoClassID
FROM AutoDataImportStaging.dbo.Automobile as A
JOIN AutoData.dbo.AutoClass as B on (A.AutoClassName = B.AutoClassName)

पृष्ठभूमि

  • सर्वर 2008 R2 पर MSSQL 2008 R2 का उपयोग करना
  • सर्वर में 8 जीबी रैम है
  • सर्वर में एक RAID10, 7200 RPM SATA है (महान नहीं, मुझे पता है, उत्पादन में यह केवल डेटा पढ़ेगा और डेटा नहीं लिखेगा; हाल ही में एचडी की कमी ने लागत के लिए यह आवश्यक बना दिया है)
  • सर्वर में डुअल क्वाड-कोर Xeon CPU है
  • मशीन कुछ और नहीं कर रही है (वर्तमान में देव को समर्पित है, केवल यह प्रक्रिया)
  • सरल लॉगिंग चालू हुई (-? लेकिन क्या यह अभी भी लॉग करता है ताकि यह रोलबैक हो सके?)
  • ध्यान दें कि क्वेरी दो अलग-अलग DB का संदर्भ देती है, जो कि इसके लायक है
  • अद्यतन की जा रही तालिका में रिकॉर्ड की "चौड़ाई" 455 बाइट्स है

निष्पादन के दौरान संसाधन

  • भौतिक रैम अधिकतम है
  • डिस्क I / O को अधिकतम किया जाता है
  • सीपीयू शायद ही कुछ कर रहा है (चोक पॉइंट आई / ओ है)
  • रन टाइम 14 घंटे और गिनती है!

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

मुझे अपने शेष सामान्यीकरण अपडेट (इस के समान) के लिए अपनी कार्यप्रणाली को और अधिक तेज़ी से कैसे बदलना चाहिए?

जवाबों:


7

आप इसे एकल (बहुत बड़े) लेनदेन के रूप में करने की कोशिश कर रहे हैं। इसके बजाय, अद्यतन छोटे बैचों में करें।

आप भी इससे लाभान्वित होंगे:

  • AutoData.dbo.AutoClass.AutoClassName पर एक अस्थायी सूचकांक
  • अधिक रैम। लॉट की अधिक रैम।

1
+1 TOPखंड के उपयोग से बैच अपडेट से मैं सहमत हूं । यही मेरा दृष्टिकोण होगा।
थॉमस स्ट्रिंगर

अगर मैं TOPDATE करता हूं तो मुझे WHERE क्लॉज़ की आवश्यकता होगी (WHERE AutoClassID is NULL)? नहीं होगा जहां एक नया प्रदर्शन हिट (एक टेबल स्कैन मैं अब नहीं कर रहा हूँ) खंड शुरू होगा। इसमें कोई शक नहीं है कि यह RAM की समस्या को कम करेगा जो मैं JOIN के साथ कर रहा हूँ।
क्रिस एड्रैगन

मेरी प्रतिक्रिया बहुत लंबी है, लेकिन मेरे मामले में, SET ROWCOUNT सबसे प्रभावी साबित हुई।
क्रिस एड्रैगन

10

मैं एक अलग तरीका अपनाऊंगा।

मौजूदा तालिकाओं को अपडेट करने के बजाय, बस एक नई तालिका बनाएं जिसमें आपके लिए आवश्यक है।

यह लगभग निश्चित रूप से तेज़ होगा:

SELECT DISTINCT
    AutoClassID,
    <Other fields>
INTO
    AutoDataImportStaging.dbo.Automobile
FROM
    AutoData.dbo.AutoClass

जैसा कि वर्तमान में लिखा गया है, बहुत सारे तार्किक संचालन हो रहे हैं:

  • A.AutoClassName के सभी मूल्यों को पढ़ें
  • B.AutoClassName के सभी मूल्यों को पढ़ें
  • A और B मान की तुलना करें
  • मिलान सेट में से, B.AutoClassID के सभी मूल्यों को पढ़ें
  • A.AutoClassId के मौजूदा मूल्यों को अपडेट करें

यह एक अच्छा, सरल दृष्टिकोण लगता है, विशेष रूप से डिस्क I / O समस्या को देखते हुए। इतनी जल्दी जवाब देने के लिए धन्यवाद।
क्रिस एड्रैगन

1
मेरा सुझाव है कि आप अपने लॉग और डेटा फ़ाइलों में पर्याप्त खाली स्थान होने की जाँच करें। यदि फ़ाइलें स्वतः-बढ़ती हैं, तो प्रदर्शन नाक-डुबकी होगा। मैं अक्सर लोगों को कुछ बड़े, एकबारगी अपडेट और ऑटो लॉग को बिना देखे ही अपने मोबाइल से बढ़ाता हुआ देखता हूं।
यारिन

5

एक समय में तालिका एक पंक्ति नीचे लूपिंग, तेज नहीं होगी!

जैसा कि संदेह है, और आपके द्वारा पुष्टि की गई है, यह i / o बाध्य होगा - एक डिस्क होने, पढ़ने, लिखने, लेन-देन लॉग और (कोई भी) अस्थायी कार्य स्थान सभी एक ही i / o के लिए प्रतिस्पर्धा करेंगे।

साधारण वसूली अभी भी लेनदेन लॉग करेगी, लेकिन लॉग को चेकपॉइंट से साफ किया जाएगा। यह संभव है कि आप प्रारंभिक लॉग आकार और ऑटो-वृद्धि सेटिंग्स कुछ i / o धीमा कर रहे हैं - परिवर्तनों को समायोजित करने के लिए लेनदेन लॉग को बढ़ने की आवश्यकता होगी।

क्या आपने AutoClassName फ़ील्ड को अनुक्रमित करने का प्रयास किया है? कितने अलग-अलग ऑटोक्लास मान हैं?

आपको अपने i / o की सीमाओं के आधार पर अपडेट को बैचने की आवश्यकता हो सकती है। इसलिए 1 मिलियन, चेकपॉइंट, रिपीट अपडेट करें ...।


केवल 15 अलग-अलग ऑटोक्लास मान हैं। आपकी टिप्पणियाँ मेरे कई संदेह (और पीड़ा!) की पुष्टि करती हैं। जवाब देने के लिए शुक्रिया।
क्रिस एड्रैगन

3

ज्वाइनिंग फील्ड के लिए इंडेक्स बनाएं।

जब आप समाप्त कर लेते हैं तो आप हमेशा अनुक्रमित छोड़ सकते हैं।

मुझे बहुत आश्चर्य होगा यदि अनुक्रमणिका ने अद्यतन प्रदर्शन में उल्लेखनीय सुधार नहीं किया।


मुझे यकीन है कि सूचकांक में सुधार होगा। मुझे लगता है कि सवाल यह है कि क्या वे सूचकांक बनाने में लगने वाले समय से अधिक सुधार करते हैं (केवल एक उपयोग के लिए)। शायद हाँ। :)
क्रिस एड्रैगन

3

अपनी इच्छानुसार निर्यात करें, एक नई तालिका बनाएं और वापस आयात करें। एक बोनस के रूप में, आपके पास बैकअप के रूप में डेटा की एक प्रति होगी, चमत्कार होना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.