2015-10-19 11 views
13

मैं एसक्यूएल में कुछ प्रश्नों को चलाने के लिए सबसे अच्छा तरीका देखने के लिए हाल ही में अपना सर्वश्रेष्ठ प्रदर्शन कर रहा हूं जो संभावित रूप से कई अलग-अलग तरीकों से किया जा सकता है। मेरे शोध में, यह कहां काम करता है, इसकी अंतर्निहित अक्षमता के कारण, जहां अवधारणा में है, के लिए मुझे बहुत नफरत है।एसक्यूएल अद्यतन (सूची) या प्रत्येक व्यक्तिगत रूप से अद्यतन करें?

जैसे: WHERE Col IN (val1, val2, val3)

मेरे वर्तमान परियोजना में, मैं डेटा के एक बड़े सेट पर एक अद्यतन कर रहा हूँ और सोच रहा हूँ जो निम्न में से अधिक कुशल है: (या एक बेहतर विकल्प मौजूद है या नहीं)

UPDATE table1 SET somecolumn = 'someVal' WHERE ID IN (id1, id2, id3 ....); 

उपर्युक्त में, आईडी की सूची 1.5k आईडी तक हो सकती है।

वी.एस.

कोड में सभी आईडी के माध्यम से लूपिंग, और प्रत्येक के लिए निम्नलिखित कथन चल:

UPDATE table1 SET somecolumn = 'someVal' WHERE ID = 'theID'; 
अपने आप को करने के लिए

, यह अधिक तार्किक लगता है कि पूर्व बेहतर, तेज़ काम करेगा/वहाँ है, क्योंकि कम चलाने के लिए सवाल। उस ने कहा, मैं एसक्यूएल के इन और आउट के साथ 100% परिचित नहीं हूं और क्वेरी क्यूइंग कैसे काम करता है।

मुझे यह भी अनिश्चितता है कि डीबी पर टेबल लॉक और अन्य सामान्य प्रदर्शन के रूप में मित्रवत होगा।

सामान्य जानकारी अगर यह मदद करता है, तो मैं माइक्रोसॉफ्ट एसक्यूएल सर्वर 2014 का उपयोग कर रहा हूं, और प्राथमिक विकास भाषा सी # है।

किसी भी मदद की बहुत सराहना की जाती है।

संपादित करें:

विकल्प 3:

UPDATE table1 SET somecolumn = 'someVal' WHERE ID IN (SELECT ID FROM @definedTable); 

ऊपर में, @definedTable किसी SQL 'उपयोगकर्ता निर्धारित तालिका प्रकार', जहां डाटा के अंदर के माध्यम से के रूप में एक संग्रहीत प्रक्रिया के लिए (सी # में आता है) टाइप SqlDbType.Structured

लोग कैसे पहचान पत्र में आते हैं पूछ रहे हैं: आईडी के कोड में एक List<string> में हैं, और फिर से पहले कोड में अन्य बातों के लिए उपयोग किया जाता एक संग्रहीत प्रक्रिया के लिए भेजा जा रहा है। वर्तमान में, आईडी संग्रहीत प्रक्रिया में केवल एक कॉलम (आईडी) के साथ 'उपयोगकर्ता-परिभाषित तालिका प्रकार' के रूप में आ रही है।

मैं उन्हें एक तालिका में होने सोचा कि id1, id2, id3, id4 आदि की तरह दिखता है एक चर

+1

क्या आपने निष्पादन योजना को देखने का प्रयास किया है यदि दो प्रश्नों से तेज़ है? – Japongskie

+1

आईडी 1, आईडी 2, आईडी 3 कहां से आ रहे हैं? कुछ व्यावहारिक मामलों में वे कुछ शर्त पर फ़िल्टरिंग के परिणामस्वरूप, दूसरी तालिका से आते हैं। सभ्य प्रदर्शन प्राप्त करने के लिए, इस मामले में आप उस तालिका के साथ जुड़ने से बेहतर होगा। –

+1

आप इन आईडी को SQL में कैसे पास कर रहे हैं? क्या आपके पास अपने सी # कोड में मूल्यों की एक सूची है या क्या आप उन्हें किसी अन्य SQL क्वेरी के परिणामस्वरूप प्राप्त करते हैं? – DavidG

उत्तर

5

मैं अपने तीसरे विकल्प का उपयोग कर रहा है और यह बहुत अच्छा काम करता है।

मेरी संग्रहीत प्रक्रिया में table-valued parameter है। Use Table-Valued Parameters भी देखें।

प्रक्रिया में, एक बयान, कोई छोरों है जैसे आप ने कहा:

UPDATE table1 SET somecolumn = 'someVal' WHERE ID IN (SELECT ID FROM @definedTable); 

यह, एक बार प्रक्रिया कॉल करने के लिए 1,500 बार से बेहतर है। 1,500 लेनदेन से एक लेनदेन होना बेहतर है।

यदि @definedTable में पंक्तियों की संख्या ऊपर जाती है, तो कहें, 10 के, मैं इसे 10 के बैचों में विभाजित करने पर विचार करता हूं।


आपका पहला संस्करण IN खंड में कुछ मूल्यों के लिए ठीक है, लेकिन आप this answer में दिखाया गया है कुछ इस तरह देख सकते हैं, जब आप वास्तव में उच्च संख्या (60K +) के लिए मिलता है:

संदेश 8623, स्तर 16, राज्य 1, रेखा 1 क्वेरी प्रोसेसर आंतरिक संसाधनों से बाहर चला गया और एक क्वेरी योजना नहीं दे सका। यह दुर्लभ ईवेंट है और केवल जटिल जटिल प्रश्नों या प्रश्नों के लिए अपेक्षित है जो बहुत बड़ी संख्या में तालिकाओं या विभाजनों का संदर्भ देते हैं। कृपया क्वेरी को सरल बनाएं। अगर आपको लगता है कि आपको यह संदेश गलती से प्राप्त हुआ है, तो अधिक जानकारी के लिए ग्राहक सहायता सेवाओं से संपर्क करें।

1

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

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

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

संपादित करें:

पर्ल स्यूडोकोड नीचे वर्णित के रूप में:

#!/usr/bin/perl 
use DBI; 
$dbh = DBI->connect('dbi:Oracle:MY_DB', 'scott', 'tiger', { RaiseError => 1, PrintError =>1, AutoCommit => 0 }); 
$sth = $dbh->prepare ("UPDATE table1 SET somecolumn = ? WHERE id = ?"); 
foreach $tuple (@updatetuples) { 
    $sth->execute($$tuple[1], $$tuple[0]); 
} 
$dbh->commit; 
$sth->finish; 
$dbh->disconnect; 
exit (0); 
+0

में अंतर क्यों नहीं किया, मैंने सोचा कि डेटा आपके प्रोग्राम से आ रहा है, नहीं एक और टेबल यह पूरी तरह स्पष्ट नहीं है। लेकिन उस मामले में, मुझे अभी भी लगता है कि यह सबसे अच्छा मार्ग है। मुझे सी # पता नहीं है, तो यहां कुछ अनचाहे पर्ल छद्म कोड है: ओह, मुझे लगता है कि मुझे इसे एक जवाब में रखना होगा। – Laserbeak

2

आपका पहला या तीसरा विकल्प जाने का सबसे अच्छा तरीका है। उनमें से किसी के लिए, आप table1(id) पर एक इंडेक्स चाहते हैं।

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

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