Du har ett antal alternativ.
Låt DB göra jobbet
Skapa en kopia av din tabell med ett unikt index - och infoga sedan data i den från din källtabell:
CREATE TABLE clean LIKE pst_nw;
ALTER IGNORE TABLE clean ADD UNIQUE INDEX (add1, add2, add3, add4);
INSERT IGNORE INTO clean SELECT * FROM pst_nw;
DROP TABLE pst_nw;
RENAME TABLE clean pst_nw;
Fördelen med att göra saker på det här sättet är att du kan verifiera att din nya tabell är korrekt innan du släpper din källtabell. Nackdelen är att den tar dubbelt så mycket plats och är (relativt) långsam att utföra.
Låt DB göra jobbet #2
Du kan också uppnå önskat resultat genom att göra:
set session old_alter_table=1;
ALTER IGNORE TABLE pst_nw ADD UNIQUE INDEX (add1, add2, add3, add4);
Det första kommandot krävs som en lösning för att ignoreringsflaggan .. ignoreras
Fördelen här är att det inte är något att bråka med en tillfällig tabell - nackdelen är att du inte kan kontrollera att din uppdatering gör exakt vad du förväntar dig innan du kör den.
Exempel:
CREATE TABLE `foo` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`one` int(10) DEFAULT NULL,
`two` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
)
insert into foo values (null, 1, 1);
insert into foo values (null, 1, 1);
insert into foo values (null, 1, 1);
select * from foo;
+----+------+------+
| id | one | two |
+----+------+------+
| 1 | 1 | 1 |
| 2 | 1 | 1 |
| 3 | 1 | 1 |
+----+------+------+
3 row in set (0.00 sec)
set session old_alter_table=1;
ALTER IGNORE TABLE foo ADD UNIQUE INDEX (one, two);
select * from foo;
+----+------+------+
| id | one | two |
+----+------+------+
| 1 | 1 | 1 |
+----+------+------+
1 row in set (0.00 sec)
Gör inte den här typen av saker utanför DB
Speciellt med 40 miljoner rader som gör något sådant här utanför db kommer sannolikt att ta enormt lång tid och kanske inte slutföras alls. Alla lösningar som stannar i db kommer att vara snabbare och mer robusta.