यदि आपको इसे लाखों बार करने की आवश्यकता है, तो यहां प्रदर्शन संबंधी समस्याओं का एक समूह है।
-
आप एक ही SQL कथन को बार-बार, लाखों बार तैयार कर रहे हैं। इसे एक बार तैयार करना और लाखों बार निष्पादित करना बेहतर होगा।
-
आप एक क्वेरी के बाद प्रत्येक फ़ंक्शन कॉल पर डेटाबेस से डिस्कनेक्ट कर रहे हैं। इसका मतलब है कि आपको हर बार फिर से कनेक्ट करने की आवश्यकता है और कोई भी कैश्ड जानकारी फेंक दी जाती है। ऐसा मत करो, इसे जुड़ा रहने दो।
-
आप प्रत्येक पंक्ति के बाद कर रहे हैं। यह चीजों को धीमा कर देगा। इसके बजाय, बैच करने के बाद कमिट करें।
-
सेलेक्ट + अपडेट या इंसर्ट शायद सिंगल अप्सर्ट के रूप में किया जा सकता है।
-
आप एक अस्थायी तालिका में इतना कुछ सम्मिलित कर रहे हैं शायद यह एक प्रदर्शन समस्या है।
-
यदि तालिका में बहुत अधिक अनुक्रमणिकाएँ हैं जो सम्मिलन को धीमा कर सकती हैं। कभी-कभी इंडेक्स को छोड़ना, एक बड़ा बैच अपडेट करना और उन्हें फिर से बनाना सबसे अच्छा होता है।
-
क्योंकि आप सीधे अपने SQL में मान डाल रहे हैं, आपका SQL एक SQL इंजेक्शन हमले ।
इसके बजाय...
- तैयार किए गए कथनों का उपयोग करें और मापदंडों को बांधें
- डेटाबेस को कनेक्ट रहने दें
- बल्क में अपडेट करें
- अपडेट चलाने के अंत में ही प्रतिबद्ध हों
- सारा गणित
UPDATE
में करें इसके बजायSELECT + math + UPDATE
। SELECT
. के बजाय "UPSERT" का इस्तेमाल करें फिरUPDATE
याINSERT
सबसे पहले, तैयार बयान। ये MySQL को एक बार स्टेटमेंट को संकलित करने देते हैं और फिर उसका पुन:उपयोग करते हैं। विचार यह है कि आप मानों के लिए प्लेसहोल्डर्स के साथ एक स्टेटमेंट लिखें।
select id, position, impressions, clicks, ctr
from temp
where profile_id=%s and
keyword=%s and
landing_page=%s
फिर आप इसे मानों के साथ तर्क के रूप में निष्पादित करते हैं, न कि स्ट्रिंग के भाग के रूप में।
self.cursor.execute(
'select id, position, impressions, clicks, ctr from temp where profile_id=%s and keyword=%s and landing_page=%s',
(profile_id, keyword, landing_page)
)
यह डेटाबेस को तैयार कथन को कैश करने की अनुमति देता है और इसे हर बार पुन:संकलित करने की आवश्यकता नहीं होती है। यह एक SQL इंजेक्शन हमले से भी बचता है जहाँ एक चतुर हमलावर एक मान तैयार कर सकता है जो वास्तव में अधिक SQL है जैसे " MORE SQL HERE "
. यह एक बहुत, बहुत, बहुत ही सामान्य सुरक्षा छेद है।
ध्यान दें, आपको MySQL का उपयोग करने की आवश्यकता हो सकती है सही तैयार विवरण प्राप्त करने के लिए पायथन डेटाबेस लाइब्रेरी . इसके बारे में बहुत अधिक चिंता न करें, तैयार कथनों का उपयोग करना आपकी सबसे बड़ी प्रदर्शन समस्या नहीं है।
इसके बाद, आप मूल रूप से जो कर रहे हैं वह मौजूदा पंक्ति में जोड़ रहा है, या यदि कोई मौजूदा पंक्ति नहीं है, तो एक नई पंक्ति डालें। इसे UPSERT
. के साथ एक ही स्टेटमेंट में अधिक कुशलता से किया जा सकता है , एक संयुक्त INSERT
और UPDATE
. MySQL के पास यह INSERT ... ON DUPLICATE KEY UPDATE
के रूप में है
।
यह देखने के लिए कि यह कैसे किया जाता है, हम आपका SELECT then UPDATE
. लिख सकते हैं एकल UPDATE
के रूप में . गणना SQL में की जाती है।
update temp
set impressions = impressions + %s,
clicks = clicks + %s,
ctr = (ctr + %s / 2)
where profile_id=%s and
keyword=%s and
landing_page=%s
आपका INSERT वही रहता है...
insert into temp
(profile_id, landing_page, keyword, position, impressions, clicks, ctr)
values (%s, %s, %s, %s, %s, %s, %s)
उन्हें एक INSERT ON DUPLICATE KEY UPDATE में संयोजित करें।
insert into temp
(profile_id, landing_page, keyword, position, impressions, clicks, ctr)
values (%s, %s, %s, %s, %s, %s, %s)
on duplicate key update
update temp
set impressions = impressions + %s,
clicks = clicks + %s,
ctr = (ctr + %s / 2)
यह इस बात पर निर्भर करता है कि तालिका की कुंजियों को किस रूप में परिभाषित किया गया है। यदि आपके पास unique( profile_id, landing_page, keyword )
. है तो इसे आपके कोड की तरह ही काम करना चाहिए।
अगर आप अपरर्ट नहीं भी कर सकते हैं, तो भी आप SELECT
. को हटा सकते हैं UPDATE
. को आजमाकर , जाँच कर रहा है कि क्या इसने कुछ अपडेट किया है, और यदि यह INSERT
नहीं कर रहा है ।
अपडेट थोक में करें। एक सबरूटीन को कॉल करने के बजाय जो एक अद्यतन करता है और करता है, इसे अद्यतन करने के लिए चीजों की एक बड़ी सूची पास करें और लूप में उन पर काम करें। आप executemany
का भी लाभ उठा सकते हैं
एकाधिक मानों के साथ एक ही कथन को चलाने के लिए। फिर प्रतिबद्ध करें।
आप UPSERT
करने में सक्षम हो सकते हैं थोक में। INSERT
एक साथ कई पंक्तियाँ ले सकते हैं। उदाहरण के लिए, यह तीन पंक्तियों को सम्मिलित करता है।
insert into whatever
(foo, bar, baz)
values (1, 2, 3),
(4, 5, 6),
(7, 8, 9)
आप संभवतः अपने INSERT ON DUPLICATE KEY UPDATE
. के साथ भी ऐसा ही कर सकते हैं डेटाबेस से बात करने के लिए ओवरहेड की मात्रा को कम करना। उदाहरण के लिए इस पोस्ट को देखें
(PHP में, लेकिन आपको अनुकूलन करने में सक्षम होना चाहिए)।
यह अंतिम सम्मिलित पंक्ति की आईडी लौटाता है, लेकिन यह विराम है।