PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Дублиращи се редове в таблица с първичен ключ.

Отново, получавайки много по-малко време за блогове 🙂

„ГРЕШКА:не можа да се създаде уникален индекс
ПОДРОБНО:Таблицата съдържа дублирани стойности.“

Тази грешка се изхвърля от Postgres, когато срещне дублиращи се редове в таблицата с първичен ключ, като не успее някоя от тези команди REINDEX или CREATE UNIQUE INDEX.

Защо в таблица съществуват дублиращи се редове?

Не съм сигурен точно 🙂 нито някакви доказани обяснения...
Според мен има две неща.

Първо, може да е забавено създаване на индекс или ако имате споделени последователности в база данни, споделянето на две различни таблици с първичен ключ може да е причината при възстановяване на данните в таблица (pg_restore). Второ, ако на тази таблица се извършва някаква огромна транзакция и в бекенда някой внезапно е спрял екземпляра, което също може да провали индекса (първичния ключ) да сочи към десния ред.

Как да го поправя?

Е, като обичайна практика, когато срещнем дублиращи се редове в таблица (въпреки някаква причина), първо филтрираме дублиращите се редове и ги изтриваме, а по-късно чрез REINDEX трябва да решим проблема.

Заявка за намиране на дублиращи се редове:

изберете count(*),primary_column от групата table_name по primary_column с брой (*)> 1;

Дори след неуспешно изтриване на дублиращи се редове REINDEX или CREATE UNIQUE INDEX, това означава, че вашият индекс не е почистен правилно. Горната заявка може да не дава 100% ориентиран към резултатите изход, който очаквате, защото заявката ще избере индекса, който вече е повреден с дублиращи се редове. Вижте плана за обяснение по-долу.

postgres=# обяснете изберете count(*), идентификатор от групата duplicate_test по идентификатор с count(*)> 1;
ПЛАН НА ЗАЯВКАТА
------------ -------------------------------------------------- ----------------------------------------
GroupAggregate (цена=0,00. .5042,90 реда=99904 ширина=4)
Филтър:(брой(*)> 1)
-> Индексно сканиране с помощта на duplicate_test_pkey на duplicate_test (цена=0,00..3044,82 реда=99904 ширина=4)
(3 реда)

Трябва да хванем CTID на дублиращи се редове от основната таблица и да изтрием с условен израз като CTID + ПЪРВИЧЕН КЛЮЧ СТОЙНОСТ.

Поиграх малко с pg_catalogs, за да проваля таблицата с първичен ключ, за да възпроизведем сценария с подобна грешка. (Моля, не го правете)

postgres=# създаване на уникален индекс idup на duplicate_test(id);
ГРЕШКА:не можа да се създаде уникален индекс "idup"
ПОДРОБНОСТИ:Ключ (id)=(10) е дублиран.

Дефиниция и данни на моята таблица:

postgres=# d duplicate_test
Таблица "public.duplicate_test"
Колона | Тип | Модификатори
-------+-------+----------
id | цяло число | не null
име | текст |
Индекси:
"duplicate_test_pkey" ПЪРВИЧЕН КЛЮЧ, btree (id)

postgres=# изберете * от duplicate_test;
id | име
----+--------
10 | Raghav ---Дублиране
20 | Джон H
30 | Майкъл
10 | Raghav ---Дублиране
(4 реда)

Сега нека поправим това...

Стъпка 1. Създайте нова таблица от извършената таблица, като изтеглите само две стойности на колони CTID и PRIMARY KEY.

postgres=# СЪЗДАЙТЕ ТАБЛИЦА dupfinder КАТО ИЗБЕРЕТЕ ctid КАТО tid, id ОТ duplicate_test;
ИЗБЕРЕТЕ 4

Стъпка 2. Сега нека стартираме заявката за намиране на дубликати с CTID, за да получим точните дубликати.

postgres=# изберете * от dupfinder x, където съществува (изберете 1 от dupfinder y, където x.id =y.id и x.tid !=y.tid);
tid | id
-------+----
(0,1) | 10
(0,5) | 10
(2 реда)

Стъпка 3. В резултата по-горе сега можете да изтриете един ред от основната таблица (ефектната таблица) с CTID.

postgres=# изтриване от duplicate_test, където ctid='(0,5)' и id=10;
ИЗТРИВАНЕ 1

Стъпка 4. Сега вашият REINDEX или CREATE UNIQUE INDEX ще бъде успешен.

postgres=# създаване на уникален индекс idup на duplicate_test(id);
СЪЗДАВАНЕ НА ИНДЕКС

postgres=# изберете * от duplicate_test;
id | име
----+--------
10 | Рагхав
20 | Джон H
30 | Майкъл
(3 реда)

Стъпка 5. Не забравяйте да направите незабавен ВАКУУМЕН АНАЛИЗ на масата, за да актуализирате системните каталози, както и движението на CTID.

Моля, споделете вашите коментари.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Изтриване на PostgreSQL с вътрешно присъединяване

  2. Съпоставяне на PostgreSQL JSON колона към свойство на обект Hibernate

  3. Oracle към PostgreSQL:Причини за мигриране

  4. Как да върнете идентификатори на вмъквания с Ibatis (с ключова дума RETURNING)

  5. XMLTABLE в PostgreSQL