Alih-alih membuat tabel baru, Anda juga dapat memasukkan kembali baris unik ke dalam tabel yang sama setelah memotongnya. Lakukan semuanya dalam satu transaksi . Secara opsional, Anda dapat menghapus tabel sementara di akhir transaksi secara otomatis dengan ON COMMIT DROP
. Lihat di bawah.
Pendekatan ini hanya berguna jika ada banyak baris yang harus dihapus dari seluruh tabel. Untuk beberapa duplikat, gunakan polos DELETE
.
Anda menyebutkan jutaan baris. Untuk membuat operasi cepat, Anda ingin mengalokasikan buffer sementara yang cukup untuk sesi tersebut. Pengaturan harus disesuaikan sebelum buffer sementara apa pun digunakan dalam sesi Anda saat ini. Cari tahu ukuran meja Anda:
SELECT pg_size_pretty(pg_relation_size('tbl'));
Atur temp_buffers
sesuai. Kumpulkan dengan murah hati karena representasi dalam memori membutuhkan lebih banyak RAM.
SET temp_buffers = 200MB; -- example value
BEGIN;
-- CREATE TEMPORARY TABLE t_tmp ON COMMIT DROP AS -- drop temp table at commit
CREATE TEMPORARY TABLE t_tmp AS -- retain temp table after commit
SELECT DISTINCT * FROM tbl; -- DISTINCT folds duplicates
TRUNCATE tbl;
INSERT INTO tbl
SELECT * FROM t_tmp;
-- ORDER BY id; -- optionally "cluster" data while being at it.
COMMIT;
Metode ini bisa lebih baik daripada membuat tabel baru jika tergantung objek yang ada. Tampilan, indeks, kunci asing, atau objek lain yang mereferensikan tabel. TRUNCATE
membuat Anda tetap memulai dengan papan tulis yang bersih (file baru di latar belakang) dan jauh lebih cepat dibandingkan DELETE FROM tbl
dengan tabel besar ( DELETE
sebenarnya bisa lebih cepat dengan tabel kecil).
Untuk tabel besar, biasanya lebih cepat untuk menghapus indeks dan kunci asing, mengisi ulang tabel, dan membuat ulang objek ini. Sejauh menyangkut kendala fk, Anda harus yakin bahwa data baru tentu saja valid atau Anda akan mengalami pengecualian saat mencoba membuat fk.
Perhatikan bahwa TRUNCATE
membutuhkan penguncian yang lebih agresif daripada DELETE
. Ini mungkin menjadi masalah untuk tabel dengan beban yang berat dan bersamaan.
Jika TRUNCATE
bukan merupakan pilihan atau umumnya untuk tabel kecil hingga menengah, ada teknik serupa dengan CTE pemodifikasi data (Postgres 9.1 +):
WITH del AS (DELETE FROM tbl RETURNING *)
INSERT INTO tbl
SELECT DISTINCT * FROM del;
-- ORDER BY id; -- optionally "cluster" data while being at it.
Lebih lambat untuk tabel besar, karena TRUNCATE
lebih cepat ke sana. Tetapi mungkin lebih cepat (dan lebih sederhana!) Untuk tabel kecil.
Jika Anda tidak memiliki objek bergantung sama sekali, Anda dapat membuat tabel baru dan menghapus yang lama, tetapi Anda hampir tidak mendapatkan apa-apa dari pendekatan universal ini.
Untuk tabel yang sangat besar yang tidak sesuai dengan RAM yang tersedia , membuat tabel baru akan jauh lebih cepat. Anda harus mempertimbangkan ini terhadap kemungkinan masalah / overhead dengan objek yang bergantung.