2009-11-24 11 views
142

मैं अपने कोड के एक हिस्से को अनुकूलित करने की कोशिश कर रहा हूं जो डेटा को MySQL में सम्मिलित करता है। क्या मुझे एक बड़ी बहु-पंक्ति INSERT बनाने के लिए INSERT को चेन करना चाहिए या कई अलग-अलग INSERT तेजी से हैं?जो तेज़ है: एकाधिक एकल INSERT या एक बहु-पंक्ति INSERT?

उत्तर

221

http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html

समय डालने एक पंक्ति निम्नलिखित कारकों, जहां संख्याएं अनुमानित अनुपात से संकेत मिलता है से निर्धारित होता है के लिए आवश्यक:

  • कनेक्ट: (3)
  • सर्वर से क्वेरी भेज रहा है : (2)
  • पार्सिंग क्वेरी: (2)
  • पंक्ति डालने: (1 × पंक्ति का आकार)
  • सम्मिलित करना अनुक्रमणिका: (इंडेक्सों का 1 × संख्या)
  • समापन: (1)

इस से यह स्पष्ट हो जाना चाहिए कि एक बड़े बयान भेजने आप डालने प्रति 7 की एक ओवरहेड की बचत होगी बयान है, जो आगे पाठ पढ़ने में भी कहते हैं:

आप एक ही समय में एक ही ग्राहक से कई पंक्तियों डालने रहे हैं, तो एक से अधिक मान के साथ सम्मिलित करें बयानों का उपयोग एक समय में कई पंक्तियों को सम्मिलित करने के सूचीबद्ध करता है। अलग-अलग सिंगल-पंक्ति INSERT कथन का उपयोग करने से यह काफी तेज है (कुछ मामलों में कई बार तेज़)।

+12

यह उत्तर कैसे लागू होता है यदि एकाधिक एकल INSERT समान डेटाबेस लेनदेन में हैं? – Pinch

+1

एकल प्रविष्टि कथन का उपयोग करते समय मैं कितनी पंक्तियां डाल सकता हूं। क्या यह मुझे एक समय में 10000 पंक्तियों को सम्मिलित करने की अनुमति देता है? –

+2

@ पिनक ~ 1.5k अप्सर्ट (डालने/अपडेट) करते समय लेनदेन का उपयोग करके ऑपरेशन को ~ 1.5 सेकंड से ~ 0.2 सेकंड तक ले लिया गया। या दूसरे शब्दों में, यह एकल पंक्ति प्रविष्टियों की तुलना में 86% तेज बना दिया। अरे नहीं। – fgblomqvist

5

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

4

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

+0

जाने का रास्ता है क्या हुआ अगर लगातार कनेक्शन प्रयोग किया जाता है? – dusoft

+5

अभी भी ऊपर की ओर है। अकेले पारगमन समय (प्रत्येक अलग सम्मिलन के लिए और से) यदि आप हजारों आवेषण कर रहे हैं तो जल्दी से अवधारणात्मक होगा। –

2

सामान्य रूप से, कनेक्शन ओवरहेड की वजह से एकाधिक आवेषण धीमे हो जाएंगे। एक साथ कई आवेषण करना प्रति डालने की ओवरहेड की लागत को कम करेगा।

आप जिस भाषा का उपयोग कर रहे हैं उसके आधार पर, आप डीबी पर जाने से पहले अपने प्रोग्रामिंग/स्क्रिप्टिंग भाषा में बैच बना सकते हैं और बैच में प्रत्येक डालने को जोड़ सकते हैं। फिर आप एक कनेक्ट ऑपरेशन का उपयोग करके एक बड़े बैच को निष्पादित करने में सक्षम होंगे। Here's जावा में एक उदाहरण।

12

एक प्रमुख कारक यह होगा कि आप एक लेनदेन इंजन का उपयोग कर रहे हैं और क्या आपके पास ऑटोोकॉमिट है या नहीं।

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

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

मुझे लगता है कि आप एक लेनदेन इंजन (आमतौर पर innodb) का उपयोग कर रहे हैं और आपने स्थायित्व को कम करने के लिए सेटिंग्स tweaked नहीं किया है।

मैं यह भी मान रहा हूं कि आप इन प्रविष्टियों को करने के लिए एक ही थ्रेड का उपयोग कर रहे हैं। कई धागे muddies चीजों का उपयोग थोड़ा सा है क्योंकि MySQL के कुछ संस्करणों में innodb में समूह-प्रतिबद्धता काम कर रहा है - इसका मतलब है कि कई धागे अपने स्वयं के काम कर रहे हैं लेनदेन लॉग में एक ही लिख साझा कर सकते हैं, जो अच्छा है क्योंकि इसका मतलब है लगातार भंडारण के लिए कम syncs ।

दूसरी ओर, अपशॉट यह है कि आप वास्तव में बहु-पंक्ति प्रविष्टियों का उपयोग करना चाहते हैं।

एक सीमा है जिस पर इसे प्रति-उत्पादक मिलती है, लेकिन ज्यादातर मामलों में यह कम से कम 10,000 पंक्तियां होती है। तो यदि आप उन्हें 1000 पंक्तियों तक बैच करते हैं, तो आप शायद सुरक्षित हैं।

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

+0

क्या कोई कारण है कि यह काउंटर उत्पादक हो जाता है एक बिंदु? मैंने इसे पहले भी देखा है लेकिन यकीन नहीं था कि क्यों। –

+1

क्या आपको पता है कि लेनदेन का उपयोग करते हुए ** ** MySQL प्रविष्टियों को बैच करने में कोई बात नहीं है। मैं बस सोच रहा हूं कि अगर मैं अंतर्निहित लाइब्रेरी (जावा जेडीबीसी - mysql-connector-java-5.1.30) वास्तव में ऐसा नहीं कर रहा हूं, तो मैं वास्तव में बहु-मूल्यवान SQL कमांड उत्पन्न करने की परेशानी को बचा सकता हूं। – RTF

3

आप देख सकते हैं:

  • चेक कि ऑटो के लिए प्रतिबद्ध बंद है
  • ओपन कनेक्शन
  • 4000-10000 के बारे में पंक्तियों की एक एकल लेनदेन में आवेषण के कई बैचों भेजें (आकार आप देखते हैं?)
  • बंद कनेक्शन

कितनी अच्छी तरह अपने सर्वर तराजू (अपने निश्चितसाथ ठीक पर निर्भर करता है, Oracle और MSSQL), ऊपर की चीज एकाधिक धागे और एकाधिक कनेक्शन के साथ करें।

118

मुझे पता है कि मैं पूछे जाने के साढ़े सालों बाद इस सवाल का जवाब दे रहा हूं, लेकिन मैं अभी उस परियोजना से कुछ कठिन डेटा प्रदान करना चाहता हूं जो मैं अभी काम कर रहा हूं जो दिखाता है कि वास्तव में कई VALUE ब्लॉक कर रहे हैं प्रति सम्मिलन अनुक्रमिक एकल VALUE ब्लॉक INSERT कथन से अधिक तेज है।

सी # में इस बेंचमार्क के लिए मैंने जो कोड लिखा है, वह एमएसएसबीएल डेटा स्रोत (~ 1 9, 000 पंक्तियों, सभी को किसी भी लेखन शुरू होने से पहले पढ़ा जाता है) से स्मृति में डेटा पढ़ने के लिए ओडीबीसी का उपयोग करता है, और MySQL .NET कनेक्टर (MySQL.Data। *) तैयार बयान के माध्यम से एक MySQL सर्वर पर स्मृति से डेटा को स्मृति में डेटा में शामिल करने के लिए सामान। यह इस तरह से लिखा गया था कि मुझे प्रति तैयार INSERT (यानी, एक समय में एन पंक्तियां डालें, जहां मैं रन से पहले एन के मूल्य को समायोजित कर सकता हूं) को गतिशील रूप से समायोजित करने की अनुमति देता हूं।) मैंने परीक्षण भी चलाया प्रत्येक एन के लिए कई बार।

एकल VALUE ब्लॉक (उदाहरण के लिए, एक समय में 1 पंक्ति) करने से चलाने के लिए 5.7 - 5.9 सेकेंड लग गए। 3.5 सेकंड
5 पंक्तियाँ एक बार में - 3.5:: 2.2 - 2.2 सेकंड
10 पंक्तियों एक समय में: 1.7 - 1.7 सेकंड
50 पंक्तियों में

2 एक समय में पंक्तियों: अन्य मूल्यों इस प्रकार हैं एक समय: 1.17 - 1.18 सेकंड
एक समय में 100 पंक्तियां: 1.1 - 1.4 सेकंड
एक समय में 500 पंक्तियां: 1.1 - 1.2 सेकंड
एक समय में 1000 पंक्तियां: 1.17 - 1।17 सेकंड

तो हाँ, यहां तक ​​कि केवल 2 या 3 लिखने के साथ-साथ बस गति में नाटकीय सुधार (एन के कारक द्वारा रनटाइम कट) प्रदान करता है, जब तक कि आप n = 5 और n = 10 के बीच कहीं न जाएं, उस बिंदु पर सुधार स्पष्ट रूप से बंद हो जाता है, और कहीं n = 10 से n = 50 रेंज में सुधार नगण्य हो जाता है।

आशा है कि लोगों को (ए) मल्टीप्रेयर विचार का उपयोग करना है या नहीं (बी) प्रति स्टेटमेंट बनाने के लिए कितने VALUE ब्लॉक (मानते हैं कि आप डेटा के साथ काम करना चाहते हैं जो पिछले प्रश्न को धक्का देने के लिए पर्याप्त हो सकता है MySQL के लिए अधिकतम क्वेरी आकार, जो मुझे लगता है कि सर्वर पर max_allowed_packet सेट के मान के आधार पर संभवतः बड़े या छोटे स्थानों पर 16 एमबी है।)

+0

स्पष्टीकरण अनुरोध: आपका समय "प्रति पंक्ति सेकंड" या "सेकंड कुल" है। – EngrStudent

+2

सेकेंड कुल - तो प्रति पंक्ति सेकंड सेकंड है जो ~ 1 9, 000 पंक्तियों से विभाजित है। यद्यपि यह एक छोटी संख्या है, इसलिए यदि आप आसानी से तुलनीय संख्या की तलाश में हैं तो शायद पंक्ति/सेकंड एक बेहतर मीट्रिक है। –

1

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

SET FOREIGN_KEY_CHECKS=0; 
3

MYSQL 5.5 एक एसक्यूएल डालने बयान ~ 300 के लिए ~ 450ms ले लिया। जबकि नीचे दिए गए आंकड़े इनलाइन एकाधिक डालने के लिए हैं।

(25492 row(s) affected) 
Execution Time : 00:00:03:343 
Transfer Time : 00:00:00:000 
Total Time  : 00:00:03:343 

मैं कहूंगा कि इनलाइन :)

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