दिलचस्प पोस्ट
सी कॉलबैक फ़ंक्शन के रूप में एक C ++ क्लास सदस्य फ़ंक्शन का उपयोग करना जावास्क्रिप्ट में समापन के लिए एक व्यावहारिक उपयोग क्या है? केवल एक टेक्स्ट बॉक्स में टाइप किए जाने की अनुमति दें सर्वर 127.0.0.1 शेल / मोंगो.जेएस से कनेक्ट नहीं हो सका अगर आप विशेष रूप से उद्देश्य-सी में संपत्ति का उपयोग कर रहे हैं तो क्या ईवर्स को घोषित करने का कोई कारण है? तत्व आईडी के साथ जेएस फंक्शन नाम का विरोध क्यों होता है? एक फ़ाइल पर सीधा पहुंच को ब्लॉक करें, लेकिन PHP स्क्रिप्ट का उपयोग करें टीडी के भीतर स्थिति संबंधपरक / निरपेक्ष का उपयोग करना? सी में एक अच्छा हैश तालिका कार्यान्वयन की तलाश शब्दकोश कुंजी का नाम बदलें क्या C ++ संदर्भ चर लौटने का अभ्यास बुराई है? रूबी: सरणी में एक डुप्लिकेट मान कैसे प्राप्त करें और वापस लौटें? JToggleButton के चिह्न सेट और अक्षम करें CodeIgniter PHP फ़्रेमवर्क – क्वेरी स्ट्रिंग प्राप्त करने की आवश्यकता है स्विफ्ट 2 (executeFetchRequest): त्रुटि हैंडलिंग

एकाधिक INSERT विवरण बनाम एकल INSERT एकाधिक मूल्यों के साथ

मैं 1000 INSERT स्टेटमेंट्स के उपयोग के बीच एक प्रदर्शन की तुलना कर रहा हूं:

INSERT INTO T_TESTS (TestId, FirstName, LastName, Age) VALUES ('6f3f7257-a3d8-4a78-b2e1-c9b767cfe1c1', 'First 0', 'Last 0', 0) INSERT INTO T_TESTS (TestId, FirstName, LastName, Age) VALUES ('32023304-2e55-4768-8e52-1ba589b82c8b', 'First 1', 'Last 1', 1) ... INSERT INTO T_TESTS (TestId, FirstName, LastName, Age) VALUES ('f34d95a7-90b1-4558-be10-6ceacd53e4c4', 'First 999', 'Last 999', 999) 

..इन 1000 INSERT स्टेटमेंट का प्रयोग करके 1000 मानों के साथ:

 INSERT INTO T_TESTS (TestId, FirstName, LastName, Age) VALUES ('db72b358-e9b5-4101-8d11-7d7ea3a0ae7d', 'First 0', 'Last 0', 0), ('6a4874ab-b6a3-4aa4-8ed4-a167ab21dd3d', 'First 1', 'Last 1', 1), ... ('9d7f2a58-7e57-4ed4-ba54-5e9e335fb56c', 'First 999', 'Last 999', 999) 

मेरे बड़े आश्चर्य के लिए, इसके परिणाम मेरे विचार के विपरीत हैं:

  • 1000 INSERT कथन: 290 मिसे
  • 1000 मूल्यों के साथ INSERT स्टेटमेंट: 2800 मिसे

परीक्षण सीधे एमएसएसक्यूएल प्रबंधन स्टूडियो में एसक्यूएल सर्वर प्रोफाइलर के साथ माप के लिए इस्तेमाल किया जाता है (और मेरे पास इसी तरह के परिणाम सी # कोड से चल रहे हैं, SqlClient का उपयोग करते हुए, जो कि सभी डीएएल परतों roundtrips पर विचार करने के लिए और भी बढ़िया है)

क्या यह उचित या किसी तरह समझाया जा सकता है? कैसे, 10 बार (!) बदतर प्रदर्शन में एक माना जाता है कि तेज़ तरीका परिणाम होता है?

धन्यवाद।

संपादित करें: दोनों के लिए निष्पादन योजनाएं संलग्न करना: Exec योजनाएं

वेब के समाधान से एकत्रित समाधान "एकाधिक INSERT विवरण बनाम एकल INSERT एकाधिक मूल्यों के साथ"

जोड़: SQL सर्वर 2012 इस क्षेत्र में कुछ बेहतर प्रदर्शन दिखाता है लेकिन नीचे दिए गए विशिष्ट मुद्दों से निपटने में प्रतीत नहीं होता है। यह स्पष्ट रूप से SQL सर्वर 2012 के बाद अगले प्रमुख संस्करण में तय किया जाना चाहिए!

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

मैंने सोचा कि मैं इसे थोड़ा और अधिक देखता हूं, हालांकि एक पाश ( स्क्रिप्ट ) की स्थापना की और VALUES की संख्या को समायोजित करने और संकलन समय रिकॉर्ड करने की कोशिश की।

तब मैंने संकलन समय को प्रति खंड औसत संकलन समय प्राप्त करने के लिए पंक्तियों की संख्या से विभाजित किया। परिणाम नीचे हैं

ग्राफ़

अप करने के लिए 250 VALUES तक संकलन समय प्रस्तुत करता है / संकलन की संख्या में मामूली वृद्धि की प्रवृत्ति है लेकिन कुछ भी नाटकीय नहीं है

ग्राफ़

लेकिन फिर अचानक बदलाव आया है

डेटा का वह भाग नीचे दिखाया गया है

 +------+----------------+-------------+---------------+---------------+ | Rows | CachedPlanSize | CompileTime | CompileMemory | Duration/Rows | +------+----------------+-------------+---------------+---------------+ | 245 | 528 | 41 | 2400 | 0.167346939 | | 246 | 528 | 40 | 2416 | 0.162601626 | | 247 | 528 | 38 | 2416 | 0.153846154 | | 248 | 528 | 39 | 2432 | 0.157258065 | | 249 | 528 | 39 | 2432 | 0.156626506 | | 250 | 528 | 40 | 2448 | 0.16 | | 251 | 400 | 273 | 3488 | 1.087649402 | | 252 | 400 | 274 | 3496 | 1.087301587 | | 253 | 400 | 282 | 3520 | 1.114624506 | | 254 | 408 | 279 | 3544 | 1.098425197 | | 255 | 408 | 290 | 3552 | 1.137254902 | +------+----------------+-------------+---------------+---------------+ 

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

सुनिश्चित नहीं है कि यह क्यों होना चाहिए। संभवतः जब यह विशिष्ट शाब्दिक मूल्यों के लिए एक योजना तैयार कर रहा है, तो उसे कुछ गतिविधि करना चाहिए जो कि रैखिक रूप से (जैसे सॉर्टिंग) पैमाने पर नहीं है।

यह कैश्ड क्वेरी प्लान के आकार को प्रभावित नहीं करता जब मैं पूरी तरह से डुप्लिकेट पंक्तियों की एक क्वेरी की कोशिश करता हूं और न ही स्थिरांक की तालिका के आउटपुट के आदेश को प्रभावित करता है (और जैसा कि आप सॉर्टिंग के दौरान खर्च किए गए ढेर के समय में डाल रहे हैं वैसे भी भले ही यह किया भी व्यर्थ होगा)।

इसके अलावा अगर एक संकुल सूचकांक तालिका में जोड़ा जाता है तो योजना अभी भी स्पष्ट रूप से एक सॉर्ट चरण दिखाती है, इसलिए यह समय को संकलन करने के लिए सॉर्ट करने में प्रतीत नहीं होता है क्योंकि रन टाइम पर एक प्रकार से बचने के लिए।

योजना

मैंने इसे डीबगर में देखने की कोशिश की लेकिन SQL सर्वर 2008 के मेरे संस्करण के लिए सार्वजनिक प्रतीकों को उपलब्ध नहीं दिखता, इसके बजाय मुझे SQL Server 2005 में समान UNION ALL निर्माण करना था।

एक विशिष्ट स्टैक ट्रेस नीचे है

 sqlservr.exe!FastDBCSToUnicode() + 0xac bytes sqlservr.exe!nls_sqlhilo() + 0x35 bytes sqlservr.exe!CXVariant::CmpCompareStr() + 0x2b bytes sqlservr.exe!CXVariantPerformCompare<167,167>::Compare() + 0x18 bytes sqlservr.exe!CXVariant::CmpCompare() + 0x11f67d bytes sqlservr.exe!CConstraintItvl::PcnstrItvlUnion() + 0xe2 bytes sqlservr.exe!CConstraintProp::PcnstrUnion() + 0x35e bytes sqlservr.exe!CLogOp_BaseSetOp::PcnstrDerive() + 0x11a bytes sqlservr.exe!CLogOpArg::PcnstrDeriveHandler() + 0x18f bytes sqlservr.exe!CLogOpArg::DeriveGroupProperties() + 0xa9 bytes sqlservr.exe!COpArg::DeriveNormalizedGroupProperties() + 0x40 bytes sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x18a bytes sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes sqlservr.exe!CQuery::PqoBuild() + 0x3cb bytes sqlservr.exe!CStmtQuery::InitQuery() + 0x167 bytes sqlservr.exe!CStmtDML::InitNormal() + 0xf0 bytes sqlservr.exe!CStmtDML::Init() + 0x1b bytes sqlservr.exe!CCompPlan::FCompileStep() + 0x176 bytes sqlservr.exe!CSQLSource::FCompile() + 0x741 bytes sqlservr.exe!CSQLSource::FCompWrapper() + 0x922be bytes sqlservr.exe!CSQLSource::Transform() + 0x120431 bytes sqlservr.exe!CSQLSource::Compile() + 0x2ff bytes 

तो स्टैक ट्रेस में नामों को बंद करना, यह तार की तुलना करने में बहुत समय लगता है।

यह KB आलेख इंगित करता है कि DeriveNormalizedGroupProperties जो क्वेरी प्रसंस्करण के सामान्यीकरण चरण कहा जाता है के साथ जुड़ा हुआ है

इस चरण को अब बाध्यकारी या बीजगणित कहा जाता है और यह पिछले पर्स चरण से अभिव्यक्ति पेर्स ट्री आउटपुट लेता है और ऑप्टिमाइजेशन (इस मामले में तुच्छ योजना अनुकूलन) [रेफरी] के लिए आगे बढ़ने के लिए एक एजीजियस एक्सप्रेशन ट्रे (क्वेरी प्रोसेसर ट्री) आउटपुट करता है।

मैंने एक और प्रयोग ( स्क्रिप्ट ) की कोशिश की जो मूल परीक्षण को दोबारा चलाने के लिए थी लेकिन तीन अलग-अलग मामलों को देखकर।

  1. प्रथम नाम और अंतिम नाम कोई डुप्लिकेट के साथ लंबाई 10 अक्षरों के तार।
  2. प्रथम नाम और अंतिम नाम स्ट्रिंग्स लंबाई 50 अक्षर के साथ कोई डुप्लिकेट नहीं।
  3. प्रथम नाम और अंतिम नाम सभी डुप्लिकेट के साथ लंबाई 10 अक्षरों के तार।

ग्राफ़

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

संपादित करें

एक जगह जहां यह जानकारी लीवरेज है, उसे यहाँ @ लाइएव द्वारा दिखाया गया है

 SELECT * FROM (VALUES ('Lieven1', 1), ('Lieven2', 2), ('Lieven3', 3))Test (name, ID) ORDER BY name, 1/ (ID - ID) 

क्योंकि समय संकलन में यह निर्धारित कर सकता है कि Name कॉलम में कोई डुप्लिकेट नहीं है, यह रन टाइम में माध्यमिक 1/ (ID - ID) अभिव्यक्ति के द्वारा क्रमबद्ध नहीं छोड़ता है (योजना में सॉर्ट केवल एक ORDER BY कॉलम है) और शून्य त्रुटि से कोई विभाजन नहीं है उठाया है। यदि डुप्लिकेट को तालिका में जोड़ दिया जाता है तो सॉर्ट ऑपरेटर कॉलम द्वारा दो ऑर्डर दिखाता है और अपेक्षित त्रुटि उठाई जाती है।

यह बहुत आश्चर्य की बात नहीं है: छोटे डालने के लिए निष्पादन योजना को एक बार गणना की जाती है, और उसके बाद 1000 बार पुनः उपयोग किया जाता है। पार्सिंग और योजना तैयार करना जल्दी है, क्योंकि इसके साथ डेल के केवल चार मान हैं। एक 1000-पंक्ति योजना, दूसरी तरफ, 4000 मूल्यों (या 4000 मापदंडों से निपटने की जरूरत है यदि आप अपने सी # परीक्षणों को पैरामीटर करते हैं)। यह 99 9 राउंडट्रिप्स को SQL सर्वर से नष्ट करने के द्वारा आसानी से समय बचत को खा सकता है, खासकर यदि आपका नेटवर्क धीमा नहीं है

इस मुद्दे को संभवतः क्वेरी को संकलित करने के समय के साथ करना पड़ता है।

यदि आप सम्मिलित करने की गति चाहते हैं, तो आपको वास्तव में क्या करने की ज़रूरत है उन्हें लेनदेन में लपेटें:

 BEGIN TRAN; INSERT INTO T_TESTS (TestId, FirstName, LastName, Age) VALUES ('6f3f7257-a3d8-4a78-b2e1-c9b767cfe1c1', 'First 0', 'Last 0', 0); INSERT INTO T_TESTS (TestId, FirstName, LastName, Age) VALUES ('32023304-2e55-4768-8e52-1ba589b82c8b', 'First 1', 'Last 1', 1); ... INSERT INTO T_TESTS (TestId, FirstName, LastName, Age) VALUES ('f34d95a7-90b1-4558-be10-6ceacd53e4c4', 'First 999', 'Last 999', 999); COMMIT TRAN; 

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

मैं एक ऐसे ही परिस्थिति में गया जो एक सी + + प्रोग्राम (एमएफसी / ओडीबीसी) के साथ कई 100k पंक्तियों के साथ एक तालिका बदलने की कोशिश कर रहा था।

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

हालांकि, यह पता चला है कि रूपांतरण वास्तव में काफी थोड़ी अधिक समय लगा था:

  Method 1 Method 2 Method 3 Single Insert Multi Insert Joined Inserts Rows 1000 1000 1000 Insert 390 ms 765 ms 270 ms per Row 0.390 ms 0.765 ms 0.27 ms 

इसलिए, सीडीबाज़ :: एक्ज़ीक्यूट एसक्यूएल के लिए 1000 एकल कॉल एक एकल INSERT कथन (विधि 1) के साथ प्रत्येक को सीडीबाज़ :: एक्ज़ीक्यूटेबल एसक्यूएलएल के लिए एक कॉल के रूप में तेजी से दो बार के रूप में तेजी से 1000 मूल्य ट्यूपल्स (विधि 2) के साथ बहु-पंक्ति INSERT स्टेटमेंट के साथ होता है।

अद्यतन: इसलिए, अगली बात मैंने कोशिश की, एक एकल स्ट्रिंग में 1000 अलग-अलग INSERT कथन को बंडल करना था और सर्वर को निष्पादित करना (विधि 3) है। यह पता चला है कि विधि 1 की तुलना में यह थोड़ी तेज़ है।

संपादित करें: मैं माइक्रोसॉफ्ट एसक्यूएल सर्वर एक्सप्रेस संस्करण (64-बिट) v10.0.2531.0 का उपयोग कर रहा हूँ