“KESALAHAN:tidak dapat membuat indeks unik
DETAIL:Tabel berisi nilai duplikat.”
Kesalahan ini dibuang oleh Postgres ketika menemukan baris duplikat dalam tabel kunci utama dengan gagal salah satu dari perintah ini REINDEX atau CREATE UNIQUE INDEX.
Mengapa ada baris duplikat dalam tabel ?
Tidak yakin persis atau ada penjelasan yang terbukti…
Ada dua hal yang saya pikirkan.
Pertama, mungkin pembuatan indeks tertunda atau jika Anda telah berbagi urutan dalam database, berbagi di dua Tabel kunci Utama yang berbeda mungkin menjadi penyebabnya saat memulihkan data ke dalam tabel (pg_restore). Kedua, jika ada transaksi besar yang terjadi di meja itu dan di backend seseorang tiba-tiba menghentikan instance, yang mungkin juga membuat indeks (kunci utama) gagal untuk menunjuk ke baris kanan.
Bagaimana cara memperbaikinya?
Nah, sebagai praktik umum, ketika kami menemukan baris duplikat dalam tabel (terlepas dari alasan apa pun), pertama-tama kami memfilter baris duplikat dan menghapusnya, dan kemudian dengan melakukan REINDEX akan memperbaiki masalah tersebut.
Kueri untuk menemukan baris duplikat:
select count(*),primary_column from table_name group by primary_column having count(*) > 1;
Bahkan setelah menghapus baris duplikat REINDEX atau CREATE UNIQUE INDEX gagal, itu berarti indeks Anda tidak dibersihkan dengan benar. Kueri di atas mungkin tidak memberikan hasil berorientasi hasil 100% seperti yang Anda harapkan, karena kueri akan memilih indeks yang sudah rusak dengan baris duplikat. Lihat rencana penjelasan di bawah ini.
postgres=# explain select count(*),id from duplicate_test group by id having count(*) > 1;
QUERY PLAN
-------------------------------------------------------------------------------------------------------
GroupAggregate (cost=0.00..5042.90 rows=99904 width=4)
Filter: (count(*) > 1)
-> Index Scan using duplicate_test_pkey on duplicate_test (cost=0.00..3044.82 rows=99904 width=4)
(3 rows)
Kita perlu menangkap CTID dari baris duplikat dari tabel utama dan menghapus dengan pernyataan bersyarat sebagai CTID + NILAI KUNCI UTAMA.
Saya telah bermain sedikit dengan pg_catalogs untuk membatalkan Tabel Kunci Utama untuk mereproduksi skenario dengan kesalahan serupa. (Tolong jangan)
postgres=# create unique index idup on duplicate_test(id);
ERROR: could not create unique index "idup"
DETAIL: Key (id)=(10) is duplicated.
Definisi &Data Tabel Saya:
postgres=# d duplicate_test
Table "public.duplicate_test"
Column | Type | Modifiers
--------+---------+-----------
id | integer | not null
name | text |
Indexes:
"duplicate_test_pkey" PRIMARY KEY, btree (id)
postgres=# select * from duplicate_test ;
id | name
----+---------
10 | Raghav ---Duplicate
20 | John H
30 | Micheal
10 | Raghav ---Duplicate
(4 rows)
Sekarang, mari kita perbaiki ini….
Langkah 1. Buat tabel baru dari tabel yang terpengaruh dengan hanya menarik dua nilai kolom CTID dan PRIMARY KEY.
postgres=# CREATE TABLE dupfinder AS SELECT ctid AS tid, id FROM duplicate_test;
SELECT 4
Langkah 2. Sekarang, mari jalankan kueri pencari duplikat dengan CTID untuk mendapatkan duplikat yang tepat.
postgres=# select * from dupfinder x where exists (select 1 from dupfinder y where x.id = y.id and x.tid != y.tid);
tid | id
-------+----
(0,1) | 10
(0,5) | 10
(2 rows)
Langkah 3. Pada hasil di atas, sekarang Anda dapat menghapus satu baris dari tabel utama (tabel yang terpengaruh) dengan CTID.
postgres=# delete from duplicate_test where ctid='(0,5)' and id=10;
DELETE 1
Langkah 4. Sekarang, REINDEX atau CREATE UNIQUE INDEX Anda akan berhasil.
postgres=# create unique index idup on duplicate_test(id);
CREATE INDEX
postgres=# select * from duplicate_test ;
id | name
----+---------
10 | Raghav
20 | John H
30 | Micheal
(3 rows)
Langkah 5. Jangan lupa untuk segera melakukan VACUUM ANALYZE di atas meja untuk mengupdate katalog sistem serta pergerakan CTID.
Silakan bagikan komentar Anda.