PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Zduplikowane wiersze w tabeli kluczy podstawowych.

Znowu, mając bardzo mniej czasu na blogowanie 🙂

„BŁĄD:nie można utworzyć unikalnego indeksu
SZCZEGÓŁY:Tabela zawiera zduplikowane wartości”.

Ten błąd jest wyrzucany przez Postgres, gdy napotka zduplikowane wiersze w tabeli kluczy podstawowych w wyniku niepowodzenia któregokolwiek z tych poleceń REINDEX lub CREATE UNIQUE INDEX.

Dlaczego w tabeli istnieją zduplikowane wiersze?

Nie jestem pewien dokładnie 🙂 ani żadnych udowodnionych wyjaśnień…
Moim zdaniem dwie rzeczy.

Po pierwsze, może to być opóźnione tworzenie indeksu lub jeśli masz wspólne sekwencje w bazie danych, współdzielenie w dwóch różnych tabelach kluczy podstawowych może być przyczyną podczas przywracania danych do tabeli (pg_restore). Po drugie, jeśli na tym stole ma miejsce jakakolwiek duża transakcja, a na zapleczu ktoś nagle zatrzymał instancję, co może również spowodować, że indeks (klucz podstawowy) nie będzie wskazywał właściwego wiersza.

Jak to naprawić?

Cóż, zgodnie z powszechną praktyką, gdy napotykamy zduplikowane wiersze w tabeli (mimo jakiegokolwiek powodu), najpierw filtrujemy zduplikowane wiersze i usuwamy je, a później, wykonując REINDEX, powinniśmy rozwiązać problem.

Zapytanie o znalezienie zduplikowanych wierszy:

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

Nawet po usunięciu zduplikowanych wierszy REINDEX lub CREATE UNIQUE INDEX nie powiedzie się, oznacza to, że indeks nie jest prawidłowo czyszczony. Powyższe zapytanie może nie dawać w 100% zorientowanych na wynik wyników, których oczekujesz, ponieważ zapytanie wybierze indeks, który jest już uszkodzony przez zduplikowane wiersze. Zobacz plan wyjaśnień poniżej.

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)

Musimy przechwycić CTID zduplikowanych wierszy z głównej tabeli i usunąć za pomocą instrukcji warunkowej jako CTID + WARTOŚĆ KLUCZU PODSTAWOWEGO.

Bawiłem się trochę z pg_catalogs, aby zmienić tabelę kluczy podstawowych w celu odtworzenia scenariusza z podobnym błędem. (Proszę, nie rób tego)

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

Definicja i dane mojej tabeli:

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)

Teraz naprawmy to….

Krok 1. Utwórz nową tabelę z tabeli, której dotyczy, pobierając tylko dwie wartości kolumn CTID i PRIMARY KEY.

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

Krok 2. Teraz uruchommy zapytanie wyszukiwarki duplikatów z CTID, aby uzyskać dokładne duplikaty.

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)

Krok 3. Na powyższym wyniku możesz teraz usunąć jeden wiersz z głównej tabeli (tabeli z efektami) z CTID.

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

Krok 4. Teraz Twój REINDEX lub CREATE UNIQUE INDEX odniesie sukces.

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)

Krok 5. Nie zapomnij wykonać natychmiastowej ANALIZY PRÓŻNIowej na stole, aby zaktualizować katalogi systemowe oraz ruch CTID.

Podziel się swoimi komentarzami.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak wygenerować instrukcję create table sql dla istniejącej tabeli w postgreSQL?

  2. Jak używać funkcji podciągów w PostgreSQL i Redshift

  3. Postgres Error:Więcej niż jeden wiersz zwrócony przez podzapytanie użyte jako wyrażenie

  4. Tabele Postgresql istnieją, ale pobieranie relacji nie istnieje podczas wykonywania zapytania

  5. Jak korzystać z przygotowanych wyciągów z Postgresem