MySQL tablolarındaki kopyaları silmek yaygın bir sorundur, bu genellikle bu kopyaları önceden önlemek için eksik bir kısıtlamanın sonucudur. Ancak bu ortak sorun genellikle belirli yaklaşımlar gerektirir ... belirli yaklaşımlar gerektirir. Yaklaşım, örneğin, verilerin boyutuna, saklanması gereken yinelenen girişe (genellikle ilk veya sonuncusu), saklanacak dizinlerin olup olmamasına veya herhangi bir ek gerçekleştirmek isteyip istemediğimize bağlı olarak farklı olmalıdır. yinelenen veriler üzerinde eylem.
MySQL'in kendisinde de bir tablo UPDATE gerçekleştirirken aynı tabloyu bir FROM nedeninde referans gösterememe gibi bazı özellikler vardır (MySQL hatası # 1093'ü yükseltir). Bu sınırlama, geçici tablo içeren bir iç sorgu kullanılarak (yukarıdaki bazı yaklaşımlarda önerildiği gibi) aşılabilir. Ancak bu iç sorgu, büyük veri kaynaklarıyla uğraşırken özellikle iyi performans göstermez.
Bununla birlikte, hem etkili hem de güvenilir olan ve farklı ihtiyaçlara kolayca uyarlanabilen kopyaları kaldırmak için daha iyi bir yaklaşım vardır.
Genel fikir, daha fazla yinelemeden kaçınmak için genellikle benzersiz bir kısıtlama ekleyerek yeni bir geçici tablo oluşturmak ve yinelemelere dikkat ederken eski tablonuzdaki verileri yenisine yerleştirmektir. Bu yaklaşım basit MySQL INSERT sorgularına dayanır, daha fazla kopyadan kaçınmak için yeni bir kısıtlama oluşturur ve kopyaları aramak için bir iç sorgu ve bellekte tutulması gereken geçici bir tablo kullanma ihtiyacını atlar (böylece büyük veri kaynaklarını da sığdırır).
Bu şekilde elde edilebilir. Aşağıdaki sütunları içeren bir tablo çalışanımız var :
employee (id, first_name, last_name, start_date, ssn)
Yinelenen bir ssn sütunu içeren satırları silmek ve yalnızca ilk girdiyi saklamak için aşağıdaki işlem izlenebilir:
-- 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;
Teknik açıklama
- Satır # 1 , çalışan tabloyla tamamen aynı yapıya sahip yeni bir tmp_eployee tablosu oluşturur
- Satır 2, daha fazla yinelemeyi önlemek için yeni tmp_eployee tablosuna UNIQUE kısıtlaması ekler
- 3. Satır, orijinal çalışan tablosunu kimliğe göre tarar ve yinelenen girişleri yok sayarken yeni tmp_eployee tablosuna yeni çalışan girişleri ekler
- 4. satır tabloları yeniden adlandırır, böylece yeni çalışan tablosu tüm girişleri kopyalar olmadan tutar ve önceki verilerin yedek bir kopyası backup_employee tablosunda tutulur.
⇒ Bu yaklaşım kullanılarak, 1.6 M kayıt 200s daha az bir sürede 6K dönüştürüldü.
Chetan , bu işlemi izleyerek, tüm kopyalarınızı hızlı ve kolay bir şekilde kaldırabilir ve çalıştırarak UNIQUE kısıtlaması oluşturabilirsiniz:
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;
Elbette, bu süreç, kopyaları silerken farklı ihtiyaçlara uyarlamak için daha fazla değiştirilebilir. Aşağıda bazı örnekler verilmiştir.
✔ İlk girişi yerine son girişi tutma çeşidi
Bazen birincisi yerine en son yinelenen girişi tutmamız gerekir.
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. satırda, ORDER BY id DESC yan tümcesi, diğer kimliklerin önceliğe göre öncelik kazanmasını sağlar
✔ Kopyalarda bazı görevleri gerçekleştirmek için varyasyon, örneğin bulunan kopyaları saymak
Bazen bulunan yinelenen girişler üzerinde bazı işlemler yapmamız gerekir (yinelenenleri saymak gibi).
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. satırda, yeni bir sütun n_duplicates oluşturulur
- Satır # 4, INUP ... IN DUPLICATE KEY UPDATE sorgusu, yinelenen bir dosya bulunduğunda ek bir güncelleştirme gerçekleştirmek için kullanılır (bu durumda, bir sayaç artar) INSERT INTO ... ON DUPLICATE KEY UPDATE sorgusu bulunan kopyalar için farklı türde güncellemeler gerçekleştirmek için kullanılır.
✔ Otomatik artan alan kimliğini yeniden oluşturma varyasyonu
Bazen otomatik artımlı bir alan kullanırız ve dizini olabildiğince küçük tutmak için yeni geçici tabloda otomatik artımlı alanı yeniden oluşturmak için kopyaların silinmesinden yararlanabiliriz.
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. satırda, tablodaki tüm alanları seçmek yerine, id motoru atlanır, böylece DB motoru otomatik olarak yeni bir alan oluşturur
✔ Diğer varyasyonlar
İstenen davranışa bağlı olarak başka birçok değişiklik de yapılabilir. Örnek olarak, aşağıdaki sorgularda ikinci bir geçici tablo kullanılacaktır, bunun yanında 1) birincisi yerine son girdiyi tutmak; ve 2) bulunan kopyalarda bir sayacın arttırılması; ayrıca 3) giriş verisini önceki verilerdeki gibi korurken otomatik artımlı alan kimliğini yeniden oluşturun.
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;