Masz wiele opcji.
Niech DB wykona pracę
Utwórz kopię swojej tabeli z unikalnym indeksem - a następnie wstaw do niej dane z tabeli źródłowej:
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;
Zaletą robienia rzeczy w ten sposób jest możliwość sprawdzenia, czy nowa tabela jest poprawna przed usunięciem tabeli źródłowej. Wadą jest to, że zajmuje dwa razy więcej miejsca i jest (stosunkowo) powolny do wykonania.
Niech DB wykona pracę #2
Możesz również osiągnąć pożądany rezultat, wykonując:
set session old_alter_table=1;
ALTER IGNORE TABLE pst_nw ADD UNIQUE INDEX (add1, add2, add3, add4);
Pierwsze polecenie jest wymagane jako obejście dla ignorowanej flagi ignorowania
Zaletą jest to, że nie ma kłopotów z tabelą tymczasową - wadą jest to, że nie można sprawdzić, czy aktualizacja działa dokładnie tak, jak się spodziewasz, przed jej uruchomieniem.
Przykład:
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)
Nie rób tego typu rzeczy poza bazą danych
Zwłaszcza przy 40 milionach wierszy wykonanie czegoś takiego poza bazą danych prawdopodobnie zajmie dużo czasu i może wcale nie zostać zakończone. Każde rozwiązanie, które pozostanie w bazie danych, będzie szybsze i bardziej niezawodne.