PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Các hàng trùng lặp trong một bảng khóa chính.

Quay lại lần nữa, dành rất ít thời gian cho việc viết blog 🙂

“LỖI:không thể tạo chỉ mục duy nhất
DETAIL:Bảng chứa các giá trị trùng lặp.”

Lỗi này do Postgres đưa ra khi gặp các hàng trùng lặp trong bảng khóa chính do không thực hiện được bất kỳ lệnh nào trong số này REINDEX hoặc CREATE UNIQUE INDEX.

Tại sao các hàng trùng lặp lại tồn tại trong một bảng?

Không chắc chắn chính xác 🙂 cũng như không có bất kỳ lời giải thích nào được chứng minh…
Tôi nghĩ hai điều.

Thứ nhất, việc tạo chỉ mục có thể bị trì hoãn hoặc nếu bạn đã chia sẻ chuỗi trong cơ sở dữ liệu, thì việc chia sẻ trên hai Bảng khóa chính khác nhau có thể là nguyên nhân trong khi khôi phục dữ liệu vào bảng (pg_restore). Thứ hai, nếu bất kỳ giao dịch lớn nào đang diễn ra trên bảng đó và tại phần phụ trợ, ai đó đã đột ngột dừng phiên bản, điều này cũng có thể khiến chỉ mục (khóa chính) không trỏ đến đúng hàng.

Làm thế nào để khắc phục nó?

Chà, như một thực tế phổ biến, khi chúng ta gặp các hàng trùng lặp trong bảng (bất chấp lý do nào đó), trước tiên chúng ta lọc các hàng trùng lặp và xóa chúng, sau đó bằng cách thực hiện REINDEX sẽ khắc phục được sự cố.

Truy vấn để tìm các hàng trùng lặp:

select count(*),primary_column from table_name group by primary_column having count(*) > 1;

Ngay cả sau khi xóa các hàng trùng lặp REINDEX hoặc TẠO CHỈ SỐ DUY NHẤT không thành công, điều đó có nghĩa là chỉ mục của bạn không được làm sạch đúng cách. Truy vấn trên có thể không đưa ra kết quả 100% theo hướng kết quả như bạn mong đợi, bởi vì truy vấn sẽ chọn chỉ mục đã bị hỏng với các hàng trùng lặp. Xem kế hoạch giải thích bên dưới.

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)

Chúng tôi cần bắt CTID của các hàng trùng lặp từ bảng chính và xóa bằng câu lệnh điều kiện là CTID + GIÁ TRỊ TỪ KHÓA CHÍNH.

Tôi đã chơi một chút với pg_catalogs để kiểm tra Bảng khóa chính để tạo lại kịch bản với lỗi tương tự. (Xin đừng làm vậy)

postgres=# create unique index idup on duplicate_test(id);
ERROR: could not create unique index "idup"
DETAIL: Key (id)=(10) is duplicated.

Định nghĩa &Dữ liệu Bảng của Tôi:

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)

Bây giờ, hãy sửa lỗi này….

Bước 1. Tạo một bảng mới từ bảng có hiệu lực bằng cách chỉ kéo hai giá trị cột CTID và PRIMARY KEY.

postgres=# CREATE TABLE dupfinder AS SELECT ctid AS tid, id FROM duplicate_test;
SELECT 4

Bước 2. Bây giờ, hãy chạy truy vấn công cụ tìm trùng lặp với CTID để có được các bản sao chính xác.

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)

Bước 3. Theo kết quả trên, bây giờ bạn có thể xóa một hàng khỏi bảng chính (bảng có hiệu lực) bằng CTID.

postgres=# delete from duplicate_test where ctid='(0,5)' and id=10;
DELETE 1

Bước 4. Bây giờ, REINDEX hoặc TẠO CHỈ SỐ DUY NHẤT của bạn sẽ thành công.

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)

Bước 5. Đừng quên thực hiện ngay lập tức PHÂN TÍCH CHÂN KHÔNG trên bảng để cập nhật danh mục hệ thống cũng như chuyển động của CTID.

Xin vui lòng chia sẻ ý kiến ​​của bạn.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. truy vấn con trong FROM phải có bí danh

  2. Làm thế nào để giải mã PostgreSQL bytea cột hex thành int16 / uint16 trong r?

  3. Postgres ĐỂ LOOP

  4. lỗi câu lệnh sql:cột .. không tồn tại

  5. Di chuyển PostgreSQL sang Đám mây - So sánh các giải pháp từ Amazon, Google và Microsoft