MySQL में `REPLACE` और` INSERT… पर DUPLICATE KEY UPDATE` के बीच व्यावहारिक अंतर क्या हैं?


81

मुझे एक विशेष कुंजी (वास्तव में कुंजी समग्र है) के साथ एक रिकॉर्ड के सभी क्षेत्रों के मूल्यों को निर्धारित करने की आवश्यकता है, रिकॉर्ड दर्ज करना अगर ऐसी कुंजी के साथ अभी तक कोई रिकॉर्ड नहीं है।

REPLACEऐसा लगता है कि काम करना है, लेकिन एक ही समय में इसका मैनुअल पेज बताता है INSERT ... ON DUPLICATE KEY UPDATE

उनमें से मुझे क्या बेहतर चुनना चाहिए और क्यों?

इसका केवल "साइड इफ़ेक्ट" ही REPLACEमेरे दिमाग में आता है, क्योंकि यह ऑटोनॉरेमेंट वैल्यू बढ़ाएगा (सौभाग्य से मैं किसी का उपयोग नहीं करता) जबकि INSERT ... ON DUPLICATE KEY UPDATEशायद नहीं होगा। ध्यान में रखने के लिए अन्य व्यावहारिक अंतर क्या हैं? किन विशेष मामलों में REPLACEपसंद किया जा सकता है INSERT ... ON DUPLICATE KEY UPDATEऔर इसके विपरीत?


INSERT ... DUPLICATE KEY पर अद्यतन वास्तव में स्वतः अंकन काउंटर को बढ़ाता है। रिकॉर्ड अपडेट होने के लिए नहीं, बल्कि अगले रिकॉर्ड के लिए डाला गया। इसलिए यदि उच्चतम आईडी 10 है और आप एक डुप्लिकेट इंसर्ट करते हैं, और फिर एक नया यूनीक वैल्यू
डालते हैं

जवाबों:


117

REPLACEआंतरिक रूप से एक डिलीट करता है और फिर एक इंसर्ट करता है। यदि आपके पास उस पंक्ति में इंगित एक विदेशी कुंजी बाधा है तो यह समस्या पैदा कर सकता है। इस स्थिति में REPLACEविफल या बदतर हो सकता है: यदि आपकी विदेशी कुंजी को हटाने के लिए कैस्केड किया जाता है, तो REPLACEपंक्तियाँ अन्य तालिकाओं से हटा दी जाएंगी। यह तब भी हो सकता है, जबकि बाधा REPLACEऑपरेशन से पहले और बाद दोनों में संतुष्ट थी ।

का प्रयोग INSERT ... ON DUPLICATE KEY UPDATEसे बचा जाता है इस समस्या को और इसलिए पसंद है।


1
अच्छा जवाब, लेकिन मेरे वास्तविक मामले में यह समस्या पूरी नहीं होने वाली है। टक्कर का मौका हालांकि 50/50 माना जा सकता है। फिर मुझे क्या चुनना चाहिए? और जैसा INSERT ... ON DUPLICATE KEY UPDATEकि "बेहतर" दिखता है, तब कौन से विशेष मामलों में "REPLACE" एक बेहतर विकल्प हो सकता है?
इवान

3
मैंने काफी हद तक शोध किया है और जहां तक ​​मैं बता सकता हूं, INSERT के बजाय REPLACE का उपयोग करने का कोई सामान्य कारण नहीं है ... ON ON DUPLICATE KEY UPDATE। यह अनिवार्य रूप से एक विरासत विशेषता है। जब तक कोई विशेष कारण नहीं है कि आपका कोड हटाए जाने वाली पंक्तियों पर निर्भर करता है और फिर से जोड़ा जाता है, तो अनुक्रमणिका और ऑटो-इंक्रीमेंट मानों पर संबंधित प्रभावों के साथ, इसका उपयोग करने का कोई कारण नहीं प्रतीत होता है।
नाथन स्ट्रेच

2
पर REPLACEअपने पी ऑटो वृद्धि मान अद्यतन करेगा अगर यह एक करता है DELETEऔर INSERT। जो जैसा चाहता है वैसा ही होता है। मैं नहीं चाहता कि उपभोक्ता उसी पीके के तहत रिकॉर्ड ढूंढे, इसलिए उन्हें कोई पंक्तियां नहीं मिलीं। जब मैं उन्हें यह (वास्तविक अद्यतन) खोजना चाहते हैं, मैं का उपयोग करेंUPDATE
radtek

तो सवाल का दूसरा भाग: जब आप पसंद करेंगे REPLACEसे अधिक INSERT ... ON DUPLICATE KEY UPDATE? A INSERT+ DELETEकभी एक से अधिक क्यों पसंद किया जाएगा UPDATE?
लेमनपाइ

59

प्रदर्शन के संदर्भ में प्रश्न का उत्तर देने के लिए, मैंने दोनों विधियों का उपयोग करके एक परीक्षण किया


इनटाप में शामिल करें:
1. टेबल पर इंसर्ट को सम्मिलित करें 2. यदि 1 विफल हो जाता है, तो पंक्ति को हटाएं और नई पंक्ति

डालें डुप्लिकेट कुंजी पर सम्मिलित करें अपडेट में शामिल हैं: 1.
टेबल पर सम्मिलित करें
2. यदि 1 विफल रहता है,

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

मैंने अपने InnoDB टेबल पर दोनों बयानों की कोशिश की है जिसमें 62,510 प्रविष्टियाँ (केवल अद्यतन) शामिल हैं। कैम्पिंग की गति पर:
इन्टो में बदलें: 77.411 सेकंड
डुप्लिकेट की अपडेट पर डालें: 2.446 सेकंड

Insert on Duplicate Key update is almost 32 times faster.

तालिका का आकार: अमेज़न एम 3 पर 3 कॉलम के साथ 1,249,250 पंक्तियाँ


कूल आँकड़े, क्या आपने कोशिश की Insert on Duplicate Key Replace? क्या यह धीमा था?
राडेक

@radtek आप केवल लिख सकते हैं ON DUPLICATE KEY UPDATE, आप नहीं लिख सकते ON DUPLICATE KEY REPLACE। यदि आप डुप्लिकेट कुंजी पर मौजूदा पंक्ति के सभी मूल्यों को अपडेट करना चाहते हैं, तो आपको लिखना होगा ON DUPLICATE KEY UPDATE col1=VALUES(col1), col2=VALUES(col2), ...- आपको सभी कॉलमों को मैन्युअल रूप से सूचीबद्ध करना होगा।
izogfif

मुझे पता है कि मैं बस पूछ रहा था कि क्या तेज था और अद्यतन की तरह लग रहा है।
राडटेक

9

REPLACEइसके बजाय का उपयोग करते समय INSERT ... ON DUPLICATE KEY UPDATE, मैं कभी-कभी कुंजी लॉकिंग या गतिरोध समस्याओं का निरीक्षण करता हूं जब दिए गए कुंजी के लिए कई प्रश्न जल्दी से आते हैं। उत्तरार्द्ध की परमाणुता (कैस्केड को हटाने का कारण नहीं होने के अलावा) सभी इसका उपयोग करने का अधिक कारण है।


3

यदि आप सभी कॉलमों को सूचीबद्ध नहीं करते हैं, तो मुझे लगता REPLACEहै कि प्रतिस्थापित पंक्तियों में उनके डिफ़ॉल्ट मानों के साथ किसी भी असंबद्ध कॉलम को रीसेट किया जाएगा। ON DUPLICATE KEY UPDATEअपरिवर्तित कॉलम को अपरिवर्तित छोड़ देगा।


3

किन खास मामलों में रिप्लाई को INSERT पर प्राथमिकता दी जा सकती है ... ON DUPLICATE KEY UPDATE और इसके विपरीत?

मैंने अभी-अभी पता लगाया है कि एक हार्ड स्टोरेज इंजन INSERT...ON DUPLICATE KEY UPDATEस्टेटमेंट वाले टेबल्स के मामले में स्वीकार किए जाते हैं, लेकिन असफल (त्रुटि 1022 के साथ: नहीं लिख सकते हैं; टेबल में डुप्लिकेट कुंजी ...) यदि डुप्लिकेट-की उल्लंघन होता है - इस पृष्ठ पर संबंधित बुलेट बिंदु देखें MySQL संदर्भ मैनुअल के ।

सौभाग्य से, मैं एक FEDERated तालिका में परिवर्तनों को दोहराने के वांछित परिणाम प्राप्त करने के लिए अपने ट्रिगर डालने के बाद REPLACEके INSERT...ON DUPLICATE KEY UPDATEभीतर का उपयोग करने में सक्षम था ।


2

बदलें लगता है कि यह मामले में दो ऑपरेशन करता है कि कुंजी पहले से मौजूद है। शायद इसका मतलब है कि दोनों के बीच एक गति अंतर है?

(INSERT) एक अपडेट बनाम एक डिलीट + एक इंसर्ट (REPLACE)

संपादित करें: मेरे निहितार्थ की जगह धीमी हो सकती है वास्तव में पूरी तरह से गलत है। खैर, वैसे भी इस ब्लॉग पोस्ट के अनुसार ... http://www.tokutek.com/2010/07/why-insert-on-duplicate-key-update-may-be-slow-by-incurring-disk-seeks /


1

"यह संभव है कि डुप्लिकेट-की त्रुटि के मामले में, एक भंडारण इंजन एक डिलीट प्लस डालने के बजाय एक अद्यतन के रूप में REPLACE का प्रदर्शन कर सकता है, लेकिन शब्दार्थ समान हैं।"

http://dev.mysql.com/doc/refman/5.7/en/replace.html


0

REPLACE कभी-कभी आवश्यक प्रतीत होता है क्योंकि INSERT IGNORE डेटा ट्रांसफ़ॉर्मेशन के साथ काम नहीं करता है।

यदि मैं ऐसा करता हूं, तो मैं केवल अपने लिए सबसे बड़ा सेट सेट करता हूं:

INSERT IGNORE INTO सबसे बड़ी इकाइयां (स्टेटआईडी, सबसे बड़ी सिटी, स्टेटपॉप) सिलेक्ट स्टेटिड, मैक्स (city.pop) को सबसे बड़ी सिटी के रूप में, स्टेट। शहर से शहर पर जाएं। राज्य। शहर पर जाएं।

यदि मैं ऐसा करता हूं, तो मैं अनुचित रूप से ग्रुप फ़ंक्शन का उपयोग कर रहा हूं:

INSERT IGNORE INTO सबसे बड़ी इकाइयाँ (StateID, सबसे बड़ीityPop, StatePop) Select stateID, MAX (city.pop) को सबसे बड़ीityPop, State.pop शहर से शहर के राज्य पर जोड़ें। स्टेट =ID.ID. BY GROUP शहर के आधार पर। (city.pop)

और अगर मैं ऐसा करता हूं, तो MySQL कॉलम नाम को मान्यता नहीं देगा:

INSERT IGNORE INTO सबसे बड़ी इकाइयां (स्टेटआईडी, सबसे बड़ी सिटी, स्टेटपॉप) सिलेक्ट स्टेटिड, मैक्स (city.pop) को सबसे बड़ी सिटी, स्टेट.पॉप शहर से शहर पर जाएं। स्टेट। शहर = स्टेट.आईडी ग्रुप बाय सिटी.स्टेट गेट पर DUPLICATE KEY UPDATE सबसे बड़ा शहर .largestCityPop

यह काम करता है, लेकिन सिर्फ सादा बदसूरत लगता है:

INSERT IGNORE INTO सबसे बड़ी इकाइयाँ (StateID, सबसे बड़ीityPop, StatePop) का चयन करें * FROM (SELECT stateID, MAX (city.pop) को सबसे बड़ीityPop, State.pop शहर से JOIN राज्य पर स्थित करें ।stateID = state.ID GROUP by city.stateID) x DUPLICATE प्रमुख अद्यतन सबसे बड़ा करें = सबसे बड़ा पिन


खबरदार: INSERT IGNOREयदि विदेशी बाधा विफल होती है, तो क्वेरी सफलतापूर्वक समाप्त हो जाएगी (और चेतावनी जारी करेगी) ! यदि आप इस तरह की त्रुटि पकड़ना चाहते हैं, तो ON DUPLICATE KEY UPDATEबिना बेहतर उपयोग के IGNORE
izogfif
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.