MySQL में एक ट्रिगर बनाम संग्रहीत प्रक्रिया का प्रदर्शन


11

DBA.StackExchange ( रिकॉर्ड्स पर संशोधन संख्या बनाए रखने के लिए ट्रिगर के लिए सर्वोत्तम अभ्यास क्या हैं? ) पर यहां एक पोस्ट ने MySQL में प्रदर्शन के संबंध में एक दिलचस्प सवाल (कम से कम, मेरे लिए दिलचस्प) को जन्म दिया है।

संदर्भ यह है कि हम अद्यतन की गई प्रत्येक पंक्ति के लिए तालिका में एक रिकॉर्ड सम्मिलित करना चाहते हैं। पंक्ति के अपडेट होने से पहले, हम पिछले मान को संग्रहीत करना चाहते हैं और फिर स्तंभों में से एक ("संस्करण" कॉलम) में वृद्धि करते हैं।

यदि हम इसे ट्रिगर के अंदर करते हैं, तो यह अच्छी तरह से काम करता है। MySQL के लिए, ट्रिगर्स पंक्ति द्वारा पंक्तिबद्ध होते हैं , इसलिए यह एक आसान समाधान होगा। वर्तमान में तालिका में डेटा का चयन करें, इसे लॉगिंग तालिका में डालें, और नए डेटा में "संस्करण" कॉलम अपडेट करें।

हालाँकि, इस तर्क को संग्रहीत प्रक्रिया में ले जाना संभव है। यदि आप ऐसा करते हैं, तो आप सम्मिलित प्रदर्शन कर रहे हैं, तो तालिका में "संस्करण" कॉलम बढ़ाएँ। पूरी बात आधारित होगी।

इसलिए, जब इस प्रविष्टि को निष्पादित करने की बात आती है, तो क्या यह सेट-आधारित संग्रहीत कार्यविधि दृष्टिकोण या ट्रिगर आधारित दृष्टिकोण का उपयोग करने के लिए अधिक प्रदर्शनकारी होगा?

यह प्रश्न MySQL (चूंकि इसमें पंक्ति-दर-पंक्ति ट्रिगर है) के लिए है, हालाँकि यह अन्य पंक्ति-दर-पंक्ति ट्रिगर DBMS पर लागू हो सकता है।


1
एक तर्क को एक संग्रहीत प्रक्रिया में धकेलने के संबंध में ध्यान रखने वाली बात - आप किसी व्यक्ति को किसी तरह सीधे अपने ऑडिट तंत्र को दरकिनार करते हुए टेबल पर कैसे लिखते हैं, आप कितने विनम्र हैं?
बिलिंक

मैं सहमत हूँ। लेकिन पैमाने के दूसरे छोर पर, शायद आप कुछ परिस्थितियों में इस लॉगिंग को जानबूझकर बायपास करना चाहते हैं। बेशक, यह एक पूरी तरह से अलग सवाल है । मैं वास्तव में प्रदर्शन के निहितार्थ के बारे में उत्सुक हूं।
रिचर्ड

जवाबों:


7

सादगी के लिए, ट्रिगर किसी भी तरह के डेटाबेस परिवर्तनों को लागू करने के लिए जाने का रास्ता है। हालाँकि, आपको इस बात से अवगत होना चाहिए कि जब आप ट्रिगर का उपयोग करते हैं तो हुड के नीचे क्या होता है।

MySQL स्टोर किए गए प्रक्रिया प्रोग्रामिंग के अनुसार , सिर के नीचे पेज 256 "ट्रिगर ओवरहेड" निम्नलिखित कहता है:

यह याद रखना महत्वपूर्ण है कि, आवश्यकता से, ट्रिगर डीएमएल स्टेटमेंट में ओवरहेड जोड़ते हैं, जिस पर वे लागू होते हैं। ओवरहेड की वास्तविक राशि ट्रिगर की प्रकृति पर निर्भर करेगी, लेकिन --- जैसा कि सभी MySQL ट्रिगर EOW ROW के लिए निष्पादित करते हैं --- ओवरहेड बड़ी संख्या में पंक्तियों को संसाधित करने वाले बयानों के लिए तेजी से जमा हो सकता है। इसलिए आपको ट्रिगर्स में कोई भी महंगा SQL स्टेटमेंट या प्रक्रियात्मक कोड रखने से बचना चाहिए।

ट्रिगर ओवरहेड का विस्तृत विवरण पृष्ठ 529-531 पर दिया गया है। उस खंड का संक्षिप्त बिंदु निम्नलिखित बताता है:

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

ट्रिगर का उपयोग करते समय पुस्तक में उल्लेख नहीं किया गया है: जब ऑडिट लॉगिंग की बात आती है, तो कृपया इस बात से अवगत रहें कि आप डेटा को लॉग इन क्या करते हैं। मैं यह कहता हूं क्योंकि आपको एक MyISAM तालिका में प्रवेश करना चाहिए, प्रत्येक INSERT एक MyISAM तालिका में INSERT के दौरान एक पूर्ण तालिका लॉक का उत्पादन होता है। यह उच्च-यातायात, उच्च-लेनदेन वातावरण में एक गंभीर अड़चन बन सकता है। इसके अतिरिक्त, यदि ट्रिगर एक InnoDB तालिका के विरुद्ध है और आप ट्रिगर के भीतर से MyISAM में परिवर्तन लॉग करते हैं, तो यह गुप्त रूप से ACID अनुपालन को अक्षम कर देगा (यानी, ब्लॉक लेनदेन को ऑटोकॉमिट व्यवहार में कम कर देगा), जिसे वापस रोल नहीं किया जा सकता है।

InnoDB तालिकाओं और लॉगिंग परिवर्तनों पर ट्रिगर का उपयोग करते समय

  • आपके द्वारा लॉग की गई तालिका भी InnoDB है
  • आपके पास स्वतः पूर्णता बंद है
  • आपने START TRANSACTION ... COMMIT / रोलबैक ब्लॉक को अच्छी तरह से सेटअप किया

इस तरह, ऑडिट लॉग मुख्य टेबल के रूप में COMMIT / रोलबैक से लाभ उठा सकते हैं।

संग्रहीत प्रक्रियाओं का उपयोग करने के बारे में, आपको ट्रैक किए जा रहे टेबल के खिलाफ डीएमएल के हर बिंदु पर संग्रहीत प्रक्रिया को श्रमसाध्य रूप से कॉल करना होगा। आवेदन कोड की हजारों लाइनों के चेहरे पर आसानी से लॉगिंग परिवर्तन को याद कर सकता है। इस तरह के कोड को ट्रिगर में रखने से उन सभी डीएमएल स्टेटमेंट को ढूंढना समाप्त हो जाता है।

चेतावनी

ट्रिगर कितना जटिल है, इसके आधार पर, यह अभी भी एक अड़चन हो सकता है। यदि आप ऑडिट लॉगिंग में अड़चनों को कम करना चाहते हैं, तो कुछ ऐसा है जो आप कर सकते हैं। हालाँकि, इसके लिए थोड़े बुनियादी ढाँचे में बदलाव की आवश्यकता होगी।

कमोडिटी हार्डवेयर का उपयोग करते हुए, दो और DB सर्वर बनाएं

यह ऑडिट लॉगिंग के कारण मुख्य डेटाबेस (एमडी) पर लिखने के लिए I / O को कम करेगा। यहाँ आप इसे कैसे पूरा कर सकते हैं:

चरण 01) मुख्य डेटाबेस में बाइनरी लॉगिंग चालू करें।

चरण 02) एक सस्ती सर्वर का उपयोग करके, बाइनरी लॉगिंग सक्षम के साथ MySQL (एमडी के समान संस्करण) को सेटअप करें। यह डीएम होंगे। एमडी से डीएम तक सेटअप प्रतिकृति।

चरण 03) एक दूसरे सस्ते सर्वर का उपयोग करके, बाइनरी लॉगिंग अक्षम के साथ MySQL (एमडी के समान संस्करण) को सेटअप करें। प्रत्येक ऑडिट टेबल का उपयोग करने के लिए सेटअप करें --replicate-do-table । यह एयू होगा। डीएम से एयू में सेटअप प्रतिकृति।

चरण 04) mysqldump को MD से तालिका संरचनाएँ और DM और AU में लोड करें।

चरण 05) BLACKHOLE संग्रहण इंजन का उपयोग करने के लिए MD की सभी ऑडिट तालिकाएँ कनवर्ट करें

चरण 06) BLACKHOLE संग्रहण इंजन का उपयोग करने के लिए DM और AU में सभी तालिकाओं को परिवर्तित करें

चरण 07) MyISAM संग्रहण इंजन का उपयोग करने के लिए AU में सभी ऑडिट टेबल को कनवर्ट करें

जब हो जाए

  • डीएम अपने बाइनरी लॉग में एमडी और रिकॉर्ड सामान से ही नकल करेंगे
  • साथ --replicate-कर-तालिका सभी अंकेक्षण टेबल पर फिल्टर, ए.यू. डीएम से दोहराने जाएगा

यह क्या करता है एक अलग डीबी सर्वर पर स्टोर ऑडिट की जानकारी है और एमडी / सामान्य रूप से किसी भी आई / ओ गिरावट को कम करना भी है।


जबरदस्त जवाब +++ 1
b_dubb

1

इस अपडेट को बल्क में करने के लिए यहां एक तरीका दिया गया है।

इस उदाहरण के लिए

  • table_A में PRIMARY KEY id है
  • आप एक तालिका बनाते हैं, जिसे टेबल_अ_केएस 2 यूपीडेट कहा जाता है, जिसमें केवल प्राथमिक कुंजी होती है
  • आप table_A_Keys2 को पॉप्युलेट करते हैं table_A से ids को अपडेट करें जो आपको पता है कि आपको अपडेट किया जाना चाहिए

बनाने के लिए table_A_Keys2Update निम्न कार्य करें:

CREATE TABLE table_A_Keys2Update SELECT id FROM table_A;
ALTER TABLE table_A_Keys2Update ADD PRIMARY KEY (id);

आपके द्वारा तालिका_A_Keys2Update को उन आईडी से आबाद करने के बाद जिनके संशोधन संख्या को बढ़ाने की आवश्यकता है, निम्नलिखित UPDATE JOIN को उन सभी पंक्तियों की संख्या बढ़ाने के लिए जोड़ दें जिनकी आईडी दोनों तालिका_ए और तालिका_A_Keys2Update में है:

UPDATE table_A A INNER JOIN table_A_Keys2Update B USING (id)
SET A.revision = A.revision + 1;

यह एक पंक्ति क्वेरी एक ट्रिगर और एक संग्रहीत प्रक्रिया को बदल सकती है।

वैकल्पिक रूप से, आप इस एक क्वेरी को संग्रहीत कार्यविधि में रख सकते हैं और यदि आप चाहें तो इसे कॉल कर सकते हैं।


यह वास्तव में मैं डालने के बारे में उत्सुक हूँ सम्मिलित करें। यदि आप INOERT का ऑडिट करते हैं, तो जो भी हो <<प्राथमिक_गामी> जहाँ <संग्रहित प्रक्रिया से पैरामीटर> का चयन करें> आप थोक में सम्मिलित कर सकते हैं। ट्रिगर में, आप बस INSERT INTO ऑडिट वैल्यू <अद्यतन पंक्ति से डेटा> । तो, क्या एकल पंक्ति, पंक्ति-दर-पंक्ति सम्मिलित थोक प्रविष्टि की तुलना में तेज़ होगी?
रिचर्ड

सादगी के लिए, ट्रिगर बहुत बेहतर होगा 1) बशर्ते कि किसी भी चोटी के समय के बीच में प्राथमिक आवेषण bulks आवेषण का अनुभव नहीं करता है, 2) ऑडिट जानकारी को किसी भी समय ऑन-डिमांड पढ़ा जाना चाहिए, और 3) आपकी साइट कम तस्करी है।
RolandoMySQLDBA
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.