MySQL तालिकाओं पर डुप्लिकेट को हटाना एक सामान्य मुद्दा है, यह वास्तव में हाथ से पहले डुप्लिकेट से बचने के लिए एक लापता बाधा का परिणाम है। लेकिन यह आम मुद्दा आमतौर पर विशिष्ट आवश्यकताओं के साथ आता है ... इसके लिए विशिष्ट दृष्टिकोण की आवश्यकता होती है। दृष्टिकोण अलग-अलग होना चाहिए, उदाहरण के लिए, डेटा का आकार, डुप्लिकेट की गई प्रविष्टि, जिसे रखा जाना चाहिए (आम तौर पर पहला या अंतिम एक), चाहे अनुक्रमणिका रखी जाए, या क्या हम कोई अतिरिक्त प्रदर्शन करना चाहते हैं डुप्लिकेट किए गए डेटा पर कार्रवाई।
MySQL पर भी कुछ विशिष्टताएँ हैं, जैसे कि UPDATE पर प्रदर्शन करते समय FROM कारण पर एक ही तालिका को संदर्भित करने में सक्षम नहीं होने के कारण (यह MySQL त्रुटि को बढ़ाएगा # 1093)। एक अस्थायी तालिका के साथ आंतरिक क्वेरी का उपयोग करके इस सीमा को दूर किया जा सकता है (जैसा कि ऊपर कुछ दृष्टिकोणों पर सुझाव दिया गया है)। लेकिन बड़े डेटा स्रोतों के साथ काम करते समय यह आंतरिक क्वेरी विशेष रूप से अच्छा प्रदर्शन नहीं करेगी।
हालांकि, डुप्लिकेट को हटाने के लिए एक बेहतर दृष्टिकोण मौजूद है, जो कि कुशल और विश्वसनीय दोनों है, और जिसे आसानी से विभिन्न आवश्यकताओं के लिए अनुकूलित किया जा सकता है।
सामान्य विचार एक नई अस्थायी तालिका बनाने के लिए है, आमतौर पर आगे के डुप्लिकेट से बचने के लिए एक अद्वितीय बाधा जोड़ते हैं, और डुप्लिकेट का ख्याल रखते हुए अपने पूर्व तालिका से डेटा को नए में सम्मिलित करते हैं। यह दृष्टिकोण सरल MySQL INSERT प्रश्नों पर निर्भर करता है, आगे के डुप्लिकेट से बचने के लिए एक नया अवरोध बनाता है, और डुप्लिकेट की खोज के लिए एक आंतरिक क्वेरी का उपयोग करने की आवश्यकता को छोड़ देता है और एक अस्थायी तालिका जिसे मेमोरी में रखा जाना चाहिए (इस प्रकार बड़े डेटा स्रोतों को भी फिटिंग)।
इसी से इसे हासिल किया जा सकता है। हमें देखते हुए एक मेज हैनिम्नलिखित कॉलम के साथ कर्मचारी है :
employee (id, first_name, last_name, start_date, ssn)
डुप्लिकेट के साथ पंक्तियों को हटाने के लिए ssn कॉलम के , और केवल पहली प्रविष्टि पाए जाने पर, निम्नलिखित प्रक्रिया का पालन किया जा सकता है:
-- create a new tmp_eployee table
CREATE TABLE tmp_employee LIKE employee;
-- add a unique constraint
ALTER TABLE tmp_employee ADD UNIQUE(ssn);
-- scan over the employee table to insert employee entries
INSERT IGNORE INTO tmp_employee SELECT * FROM employee ORDER BY id;
-- rename tables
RENAME TABLE employee TO backup_employee, tmp_employee TO employee;
तकनीकी व्याख्या
- लाइन # 1 एक नया tmp_eployee बनाता है तालिका जिसमें कर्मचारी तालिका के समान संरचना है
- लाइन # 2 नए में एक बाधा बाधा जोड़ता है आगे के डुप्लिकेट से बचने के tmp_eployee तालिका में
- आईडी द्वारा मूल कर्मचारी तालिका पर लाइन # 3 स्कैन , नए में नई कर्मचारी प्रविष्टियाँ सम्मिलित करता है tmp_eployee तालिका करते हुए, डुप्लिकेट प्रविष्टियों की अनदेखी करते हुए
- पंक्ति # 4 तालिकाओं का नाम बदल देती है, ताकि नए कर्मचारी तालिका में डुप्लिकेट के बिना सभी प्रविष्टियां हों, और पूर्व डेटा की एक बैकअप प्रति backup_employee पर रखी जाए तालिका
⇒ इस दृष्टिकोण का उपयोग करते हुए, 1.6M रजिस्टरों को 200k से कम में 6k में बदल दिया गया।
चेतन , इस प्रक्रिया का अनुसरण करते हुए, आप तेजी से और आसानी से अपने सभी डुप्लिकेट को हटा सकते हैं और रन करके एक UNIQUE बाधा बना सकते हैं:
CREATE TABLE tmp_jobs LIKE jobs;
ALTER TABLE tmp_jobs ADD UNIQUE(site_id, title, company);
INSERT IGNORE INTO tmp_jobs SELECT * FROM jobs ORDER BY id;
RENAME TABLE jobs TO backup_jobs, tmp_jobs TO jobs;
बेशक, डुप्लिकेट को हटाते समय विभिन्न आवश्यकताओं के लिए इसे अनुकूलित करने के लिए इस प्रक्रिया को और संशोधित किया जा सकता है। कुछ उदाहरण अनुसरण करते हैं।
One पहले वाले के बजाय अंतिम प्रविष्टि रखने के लिए विविधता
कभी-कभी हमें पहले वाले के बजाय अंतिम डुप्लिकेट प्रविष्टि रखने की आवश्यकता होती है।
CREATE TABLE tmp_employee LIKE employee;
ALTER TABLE tmp_employee ADD UNIQUE(ssn);
INSERT IGNORE INTO tmp_employee SELECT * FROM employee ORDER BY id DESC;
RENAME TABLE employee TO backup_employee, tmp_employee TO employee;
- # 3 लाइन पर, ORDER BY आईडी DESC क्लॉज बाकी के ऊपर प्राथमिकता प्राप्त करने के लिए अंतिम आईडी बनाता है
✔ डुप्लिकेट पर कुछ कार्य करने के लिए भिन्नता, उदाहरण के लिए डुप्लिकेट पर एक गिनती रखते हुए
कभी-कभी हमें डुप्लिकेट प्रविष्टियों पर कुछ और प्रसंस्करण करने की आवश्यकता होती है जो पाए जाते हैं (जैसे कि डुप्लिकेट की गिनती को ध्यान में रखते हुए)।
CREATE TABLE tmp_employee LIKE employee;
ALTER TABLE tmp_employee ADD UNIQUE(ssn);
ALTER TABLE tmp_employee ADD COLUMN n_duplicates INT DEFAULT 0;
INSERT INTO tmp_employee SELECT * FROM employee ORDER BY id ON DUPLICATE KEY UPDATE n_duplicates=n_duplicates+1;
RENAME TABLE employee TO backup_employee, tmp_employee TO employee;
- लाइन # 3 पर, एक नया कॉलम n_duplicates बनाया गया है
- # 4 लाइन पर, INSERT INTO ... DUPLICATE KEY पर एक अतिरिक्त डुप्लिकेट मिलने पर अद्यतन अपडेट करने के लिए उपयोग किया जाता है (इस मामले में, एक काउंटर बढ़ाते हुए) INSERT INTO ... ON DUPLICATE कुंजी क्वेरी हो सकती है पाया डुप्लिकेट के लिए विभिन्न प्रकार के अद्यतन करने के लिए उपयोग किया जाता है।
ऑटो-वृद्धिशील क्षेत्र आईडी को पुनर्जीवित करने के लिए विविधता
कभी-कभी हम एक ऑटो-वृद्धिशील क्षेत्र का उपयोग करते हैं और, अनुक्रम को यथासंभव कॉम्पैक्ट रखने के लिए, हम नए अस्थायी तालिका में ऑटो-वृद्धिशील क्षेत्र को पुन: उत्पन्न करने के लिए डुप्लिकेट के विलोपन का लाभ उठा सकते हैं।
CREATE TABLE tmp_employee LIKE employee;
ALTER TABLE tmp_employee ADD UNIQUE(ssn);
INSERT IGNORE INTO tmp_employee SELECT (first_name, last_name, start_date, ssn) FROM employee ORDER BY id;
RENAME TABLE employee TO backup_employee, tmp_employee TO employee;
- लाइन # 3 पर, टेबल पर सभी फ़ील्ड्स का चयन करने के बजाय, आईडी फ़ील्ड को छोड़ दिया जाता है ताकि DB इंजन अपने आप एक नया इंजन उत्पन्न करे
✔ और बदलाव
वांछित व्यवहार के आधार पर कई और संशोधन भी उल्लेखनीय हैं। एक उदाहरण के रूप में, निम्नलिखित प्रश्न 1 के अलावा दूसरी अस्थायी तालिका का उपयोग करेंगे) पहले वाले के बजाय अंतिम प्रविष्टि रखें; और 2) पाए गए डुप्लिकेट पर एक काउंटर बढ़ाएं; 3) प्रविष्टि क्रम को पूर्व डेटा पर रखते समय ऑटो-वृद्धिशील फ़ील्ड आईडी पुनर्जीवित करें।
CREATE TABLE tmp_employee LIKE employee;
ALTER TABLE tmp_employee ADD UNIQUE(ssn);
ALTER TABLE tmp_employee ADD COLUMN n_duplicates INT DEFAULT 0;
INSERT INTO tmp_employee SELECT * FROM employee ORDER BY id DESC ON DUPLICATE KEY UPDATE n_duplicates=n_duplicates+1;
CREATE TABLE tmp_employee2 LIKE tmp_employee;
INSERT INTO tmp_employee2 SELECT (first_name, last_name, start_date, ssn) FROM tmp_employee ORDER BY id;
DROP TABLE tmp_employee;
RENAME TABLE employee TO backup_employee, tmp_employee2 TO employee;