जवाबों:
https://dev.mysql.com/doc/refman/8.0/en/insert-optimization.html
एक पंक्ति सम्मिलित करने के लिए आवश्यक समय निम्नलिखित कारकों द्वारा निर्धारित किया जाता है, जहां संख्या अनुमानित अनुपात दर्शाती है:
- कनेक्टिंग: (3)
- सर्वर को क्वेरी भेजना: (2)
- पार्सिंग क्वेरी: (2)
- पंक्ति सम्मिलित करना: (पंक्ति का 1 × आकार)
- अनुक्रमणिका सम्मिलित करना: (अनुक्रमणिका का 1 × संख्या)
- समापन: (1)
इससे यह स्पष्ट होना चाहिए, कि एक बड़ा बयान भेजने से आपको 7 प्रति ओवरवेट स्टेटमेंट की बचत होगी, जो आगे के पाठ को भी पढ़ता है:
यदि आप एक ही समय में एक ही क्लाइंट से कई पंक्तियों को सम्मिलित कर रहे हैं, तो एक बार में कई पंक्तियों को सम्मिलित करने के लिए कई VALUES सूचियों के साथ INSERT कथनों का उपयोग करें। यह अलग-अलग एकल-पंक्ति INSERT कथनों का उपयोग करने की तुलना में काफी तेज (कुछ मामलों में कई गुना तेज) है।
मुझे पता है कि मैं इस प्रश्न का उत्तर लगभग ढाई साल बाद दे रहा था, लेकिन मैं अभी एक प्रोजेक्ट से कुछ कठिन डेटा प्रदान करना चाहता था, जो मैं अभी काम कर रहा हूं, जिससे पता चलता है कि वास्तव में प्रति मिनट कई VALUE ब्लॉक कर रहा है MUCH अनुक्रमिक एकल VALUE ब्लॉक INSERT कथनों से तेज।
C # में इस बेंचमार्क के लिए मैंने जो कोड लिखा था, वह MSSQL डेटा स्रोत (~ 19,000 पंक्तियों, जो किसी भी लेखन शुरू होने से पहले पढ़े जाते हैं), और MySql .NET कनेक्टर (Mysql.Data।) सामान से मेमोरी में डेटा पढ़ने के लिए ODBC का उपयोग करता है। तैयार बयानों के माध्यम से MySQL सर्वर पर एक टेबल में मेमोरी से डेटा को सम्मिलित करें। यह इस तरह से लिखा गया था, ताकि मुझे तैयार INSERT के प्रति VALUE ब्लॉकों की संख्या को गतिशील रूप से समायोजित करने की अनुमति दी जा सके (अर्थात, एक समय में n पंक्तियों को सम्मिलित करें, जहां मैं एक रन से पहले n के मूल्य को समायोजित कर सकता था।) मैंने भी परीक्षण चलाया। प्रत्येक एन के लिए कई बार।
सिंगल वैल्यू ब्लॉक करना (जैसे, एक बार में 1 पंक्ति) को चलाने में 5.7 - 5.9 सेकंड लगे। अन्य मूल्य इस प्रकार हैं:
एक समय में 2 पंक्तियाँ: एक समय में 3.5 - 3.5 सेकंड
5 पंक्तियाँ: एक समय में 2.2 - 2.2 सेकंड
10 पंक्तियाँ: एक समय में 1.7 - 1.7 सेकंड
50 पंक्तियाँ: 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 सीमा में सुधार नगण्य हो जाता है।
आशा है कि लोगों को मल्टीपर्पर विचार का उपयोग करने के बारे में निर्णय लेने में मदद करता है, और (बी) प्रति कथन बनाने के लिए कितने वैल्यू ब्लॉक हैं (यह मानकर कि आप डेटा के साथ काम करना चाहते हैं जो अधिकतम क्वेरी आकार को क्वेरी को पुश करने के लिए काफी बड़ा हो सकता है। MySQL के लिए, जो मेरा मानना है कि बहुत सी जगहों पर डिफ़ॉल्ट रूप से 16MB है, संभवतः सर्वर पर max_allowed_packet सेट के मूल्य के आधार पर बड़ा या छोटा।)
एक प्रमुख कारक यह होगा कि क्या आप एक ट्रांजेक्शनल इंजन का उपयोग कर रहे हैं और क्या आपके पास ऑटोकॉमिट है।
स्वतः पूर्णता डिफ़ॉल्ट रूप से चालू है और आप संभवतः इसे छोड़ना चाहते हैं; इसलिए, प्रत्येक सम्मिलित जो आप करते हैं वह अपना लेनदेन करता है। इसका मतलब है कि यदि आप प्रति पंक्ति एक सम्मिलित करते हैं, तो आप प्रत्येक पंक्ति के लिए लेनदेन करने जा रहे हैं।
किसी एकल थ्रेड को मानते हुए, इसका अर्थ है कि सर्वर को हर डेटा को EVERY ROW के लिए डिस्क में सिंक करने की आवश्यकता है। इसे लगातार स्टोरेज लोकेशन तक पहुंचने के लिए डेटा की प्रतीक्षा करने की जरूरत है (उम्मीद है कि आपके RAID कंट्रोलर में बैटरी समर्थित रैम)। यह स्वाभाविक रूप से धीमा है और शायद इन मामलों में सीमित कारक बन जाएगा।
मैं निश्चित रूप से मान रहा हूं कि आप एक ट्रांजेक्शनल इंजन का उपयोग कर रहे हैं (आमतौर पर निर्दोष) और यह कि आपने स्थायित्व को कम करने के लिए सेटिंग्स को ट्विक नहीं किया है।
मैं यह भी मान रहा हूं कि आप इन आवेषणों को करने के लिए एक ही धागे का उपयोग कर रहे हैं। कई थ्रेड्स का उपयोग करने से चीजें थोड़ी गड़बड़ हो जाती हैं, क्योंकि MySQL के कुछ संस्करणों में वर्क-ग्रुप इन-इन्सोडब होता है - इसका मतलब है कि अपने स्वयं के काम करने वाले कई थ्रेड्स लेन-देन लॉग में एक ही लेखन साझा कर सकते हैं, जो अच्छा है क्योंकि इसका अर्थ है लगातार भंडारण के लिए कम सिंक ।
दूसरी ओर, अपशॉट यह है कि आप बहु-पंक्ति आवेषण का उपयोग करना चाहते हैं।
एक सीमा है जिस पर वह प्रति-उत्पादक हो जाता है, लेकिन ज्यादातर मामलों में यह कम से कम 10,000 पंक्तियों का होता है। इसलिए यदि आप उन्हें 1,000 पंक्तियों तक बैचते हैं, तो आप शायद सुरक्षित हैं।
यदि आप MyISAM का उपयोग कर रहे हैं, तो चीजों का एक पूरा भार है, लेकिन मैं आपको उन लोगों के साथ बोर नहीं करूंगा। शांति।
सामान्य तौर पर डेटाबेस में कॉल की कम संख्या बेहतर (मतलब तेज, अधिक कुशल) है, इसलिए आवेषण को इस तरह से कोड करने का प्रयास करें कि यह डेटाबेस एक्सेस को कम कर दे। याद रखें, जब तक आपके कनेक्शन पूल का उपयोग नहीं किया जाता है, प्रत्येक डेटाबेस एक्सेस में एक कनेक्शन बनाना होता है, एसक्यूएल निष्पादित करता है, और फिर कनेक्शन को फाड़ देता है। थोड़ा उपर से!
हो सकता है कि आप यह चाहते हों :
यह निर्भर करता है कि आपका सर्वर कितना अच्छा है (इसकी निश्चित रूप से ठीक है PostgreSQl
, Oracle
और MSSQL
), एकाधिक थ्रेड और कई कनेक्शन के साथ ऊपर की बात करें।
सामान्य तौर पर, कनेक्शन ओवरहेड होने के कारण कई आवेषण धीमे होंगे। एक साथ कई आवेषण करने से ओवरहेड की लागत प्रति इंसर्ट कम हो जाएगी।
आप किस भाषा का उपयोग कर रहे हैं, इसके आधार पर, आप संभवतः db पर जाने से पहले अपनी प्रोग्रामिंग / स्क्रिप्टिंग भाषा में एक बैच बना सकते हैं और प्रत्येक प्रविष्टि को बैच में जोड़ सकते हैं। तब आप एक कनेक्ट ऑपरेशन का उपयोग करके एक बड़े बैच को निष्पादित करने में सक्षम होंगे। यहाँ जावा में एक उदाहरण है।
यह हास्यास्पद है कि जब आवेषण की बात आती है तो माईसकल और मारियाडीबी को कितना बुरा लगता है। मैंने mysql 5.7 और mariadb 10.3 का परीक्षण किया, उन पर कोई वास्तविक अंतर नहीं था।
मैंने इसे NVME डिस्क, 70,000 IOPS, 1.1 GB / sec seq throughput के साथ एक सर्वर पर परीक्षण किया है और यह पूर्ण द्वैध (पढ़ने और लिखने) संभव है।
सर्वर एक उच्च प्रदर्शन सर्वर है।
यह 20 GB RAM दिया।
डेटाबेस पूरी तरह से खाली।
मल्टी रो इन्सर्ट करते समय मुझे प्राप्त होने वाली गति 5000 आवेषण प्रति सेकंड थी (इसे 1 एमबी के साथ 10 एमबी तक के डेटा के साथ आज़माया गया)
अब सुराग:
यदि मैं एक और धागा जोड़ता हूं और एक ही तालिका में सम्मिलित करता हूं तो मेरे पास अचानक 2x5000 / सेकंड है। एक और धागा और मेरे पास कुल 15000 / सेकंड है
इस पर विचार करें: जब एक थ्रेड आवेषण करता है, तो इसका मतलब है कि आप अनुक्रमिक रूप से डिस्क (अनुक्रमणिकाओं के अपवादों के साथ) को लिख सकते हैं। थ्रेड्स का उपयोग करते समय आप वास्तव में संभावित प्रदर्शन को नीचा दिखाते हैं क्योंकि इसे अब बहुत अधिक यादृच्छिक एक्सेस करने की आवश्यकता है। लेकिन रियलिटी चेक से पता चलता है कि mysql इतनी बुरी तरह से अनुकूलित है कि धागे बहुत मदद करते हैं।
इस तरह के सर्वर के साथ वास्तविक प्रदर्शन संभवत: लाखों प्रति सेकंड है, सीपीयू बेकार है और डिस्क बेकार है।
कारण काफी स्पष्ट है कि मेरीडब्ल के रूप में मारीदब में आंतरिक देरी है।
id
,, parent_id
VALUES (1, NULL) है। मानों के अगले सेट में से एक उस पंक्ति से लिंक करता है। यदि आप विखंडू में विभाजित हो जाते हैं और उस सेट को दूसरे चंक में ले जाया जाता है, तो इसे पहली प्रक्रिया से पहले संसाधित किया जा सकता है, पूरी प्रक्रिया को विफल कर सकता है। किसी भी विचार से कैसे निपटना है?
एकाधिक आवेषण तेज़ होते हैं लेकिन इसमें थ्रेडशोल्ड होता है। एक अन्य थ्रैड अक्षम कर रहा है कसौटी जाँच टेम्परेरी आवेषण को बहुत तेज करता है। इससे कोई फर्क नहीं पड़ता कि आपकी तालिका में यह है या नहीं। उदाहरण के लिए विदेशी कुंजियों को अक्षम करने की परीक्षा और गति का आनंद लें:
SET FOREIGN_KEY_CHECKS=0;
ऑफकोर्स आपको इसे आवेषण के बाद वापस चालू करना चाहिए:
SET FOREIGN_KEY_CHECKS=1;
यह विशाल डेटा सम्मिलित करने का सामान्य तरीका है। विदेशी प्रमुख जांच को अक्षम करने से पहले आप डेटा की अखंडता को तोड़ सकते हैं।