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

Dodawanie wielokolumnowego klucza podstawowego do tabeli z 40 milionami rekordów

Użyj kolumny szeregowej

Twoim planem jest dodanie niepotrzebnie dużego indeksu dla 40 milionów (!) wierszy. I nie jesteś nawet pewien, czy będzie wyjątkowy. Zdecydowanie odradzałbym ten sposób działania. Dodaj serial zamiast tego i skończ z tym:

ALTER TABLE tbl ADD COLUMN tbl_id serial PRIMARY KEY;

To wszystko, co musisz zrobić. Reszta dzieje się automatycznie. Więcej w instrukcji lub w tych ściśle powiązanych odpowiedziach:
Awaria automatycznego przyrostu klucza podstawowego PostgreSQL w C++
Funkcja automatycznej inkrementacji SQL

Dodawanie serii kolumna jest operacją jednorazową, ale kosztowną. Cała tabela musi zostać przepisana, blokując aktualizacje na czas trwania operacji. Najlepiej robić to bez jednoczesnego obciążenia poza godzinami pracy. Cytuję instrukcję tutaj :

Ponieważ to skutecznie przepisuje całą tabelę, równie dobrze możesz utworzyć nową tabelę z kolumną szeregowego pk, wstawić wszystkie wiersze ze starej tabeli, pozwalając szeregowemu na wypełnienie domyślnymi wartościami z jego sekwencji, upuścić starą i zmienić nazwę nowej. Więcej w tych ściśle powiązanych odpowiedziach:
Aktualizacja wierszy bazy danych bez blokowania tabeli w PostgreSQL 9.2
Dodaj nową kolumnę bez tabeli zablokować?

Upewnij się, że wszystkie instrukcje INSERT mają listę celów, a dodatkowa kolumna nie może ich pomylić:

INSERT INTO tbl (col1, col2, ...) VALUES ...

Nie:

INSERT INTO tbl VALUES ...

seryjny jest zaimplementowany z liczbą całkowitą kolumna (4 bajty).
Zaimplementowano ograniczenie klucza podstawowego z unikalnym indeksem i NOT NULL ograniczenie na zaangażowanych kolumnach.
Zawartość indeksu jest przechowywana podobnie jak tabele. Dodatkowa pamięć fizyczna jest potrzebna osobno. Więcej o pamięci fizycznej w tej powiązanej odpowiedzi:
Obliczanie i oszczędzanie miejsca w PostgreSQL

Twój indeks będzie zawierał 2 sygnatury czasowe (2 x 8 bajtów) oraz długą nazwę pliku, w tym path (~ 50 bajtów?) To spowodowałoby, że indeks byłby większy o około 2,5 GB (40M x 60…coś bajtów) i wszystkie operacje byłyby wolniejsze.

Radzenie sobie z duplikatami

Sposób radzenia sobie z „importowaniem duplikatów” zależy od tego, w jaki sposób importujesz dane i jak dokładnie zdefiniowano „duplikat”.

Jeśli mówimy o KOPIUJ instrukcji, jednym ze sposobów byłoby użycie tymczasowej tabeli pomostowej i zwinięcie duplikatów za pomocą prostego SELECT DISTINCT lub DISTINCT ON w WSTAW polecenie:

CREATE TEMP TABLE tbl_tmp AS
SELECT * FROM tbl LIMIT 0;     -- copy structure without data and constraints

COPY tbl_tmp FROM '/path/to/file.csv';

INSERT INTO tbl (col1, col2, col3)
SELECT DISTINCT ON (col1, col2)
       col1, col2, col3 FROM tbl_tmp;

Lub, aby zabronić również duplikatów z już istniejącymi wierszami:

INSERT INTO tbl (col1, col2, col3)
SELECT i.*
FROM  (
   SELECT DISTINCT ON (col1, col2)
          col1, col2, col3
   FROM   tbl_tmp
   ) i
LEFT   JOIN tbl t USING (col1, col2)
WHERE  t.col1 IS NULL;

Temp. tabela jest automatycznie usuwana pod koniec sesji.

Ale właściwą poprawką byłoby przede wszystkim zajęcie się źródłem błędu, który powoduje duplikaty.

Pierwotne pytanie

1) Nie można było w ogóle dodać pk, jeśli istnieje jeden duplikat we wszystkich kolumnach.

2) Dotknąłbym tylko bazy danych PostgreSQL w wersji 8.1 z pięciometrowym słupem. Jest beznadziejnie stary, przestarzały i nieefektywny, nie jest już wspierany i prawdopodobnie ma wiele nienaprawionych luk w zabezpieczeniach. Oficjalna witryna wersjonowania Postgres.
@David już dostarczył instrukcję SQL.

3 i 4) Zduplikowane naruszenie klucza. Zgłoszenie błędu przez PostgreSQL oznacza również wycofanie całej transakcji. Przechwycenie tego w skrypcie perla nie może spowodować przejścia reszty transakcji. Będziesz musiał na przykład utworzyć skrypt po stronie serwera za pomocą plpgsql, w którym możesz przechwytywać wyjątki.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. prawidłowy sposób uruchamiania/zatrzymywania bazy danych postgres pg_ctl lub obsługi postgres

  2. Złożona kwestia „Gaps and Islands”

  3. W jaki sposób strona FROM UPDATE ma się do tabeli przeznaczonej dla UPDATE?

  4. Pole rails, które jest tablicą obiektów JSON?

  5. Jak replikować tylko WSTAWKI, a nie DELETE/AKTUALIZACJE na węźle Slony Slave?