PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Aggiunta di una chiave primaria a più colonne a una tabella con 40 milioni di record

Utilizza una colonna seriale

Il tuo piano è aggiungere un indice inutilmente enorme per 40 milioni (!) di righe. E non sei nemmeno sicuro che sarà unico. Sconsiglio vivamente questa via d'azione. Aggiungi un serial colonna invece e basta:

ALTER TABLE tbl ADD COLUMN tbl_id serial PRIMARY KEY;

Questo è tutto ciò che devi fare. Il resto avviene automaticamente. Maggiori informazioni nel manuale o in queste risposte strettamente correlate:
L'incremento automatico della chiave primaria PostgreSQL si arresta in modo anomalo in C++
Funzione SQL di incremento automatico

Aggiunta di un serial colonna è un'operazione una tantum, ma costosa. L'intera tabella deve essere riscritta, bloccando gli aggiornamenti per la durata dell'operazione. È meglio farlo senza carico simultaneo nelle ore di riposo. Cito il manuale qui :

Poiché questo riscrive efficacemente l'intera tabella, potresti anche creare una nuova tabella con una colonna seriale pk, inserire tutte le righe dalla vecchia tabella, lasciare che la seriale riempia con i valori predefiniti dalla sua sequenza, eliminare il vecchio e rinominare il nuovo. Altro in queste risposte strettamente correlate:
Aggiornamento delle righe del database senza bloccare la tabella in PostgreSQL 9.2
Aggiungi nuova colonna senza tabella bloccare?

Assicurati che tutte le tue istruzioni INSERT abbiano un elenco di destinazione, quindi una colonna aggiuntiva non può confonderle:

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

Non:

INSERT INTO tbl VALUES ...

Un serial è implementato con un integer colonna (4 byte).
Un vincolo di chiave primaria viene implementato con un indice univoco e un NOT NULL vincolo sulle colonne coinvolte.
Il contenuto di un indice viene archiviato in modo molto simile alle tabelle. Lo spazio di archiviazione fisico aggiuntivo è necessario separatamente. Maggiori informazioni sull'archiviazione fisica in questa risposta correlata:
Calcolo e risparmio di spazio in PostgreSQL

Il tuo indice includerebbe 2 timestamp (2 x 8 byte) più un nome file lungo incl. percorso (~ 50 byte?) Ciò renderebbe l'indice più grande di circa 2,5 GB (40 M x 60 .. qualcosa di byte) e tutte le operazioni più lente.

Gestire i duplicati

La gestione dell'"importazione di duplicati" dipende da come stai importando i dati e da come viene definito esattamente "duplicato".

Se stiamo parlando di COPY istruzioni, un modo sarebbe utilizzare una tabella di staging temporanea e comprimere i duplicati con un semplice SELECT DISTINCT o DISTINCT ON nel INSERT comando:

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;

Oppure, per vietare anche i duplicati con righe già esistenti:

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;

La temp. la tabella viene eliminata automaticamente alla fine della sessione.

Ma la soluzione corretta sarebbe occuparsi della radice dell'errore che produce duplicati in primo luogo.

Domanda originale

1) Non è possibile aggiungere affatto il pk, se è presente un singolo duplicato su tutte le colonne.

2) Toccherei solo un database PostgreSQL versione 8.1 con un palo di cinque piedi. È irrimediabilmente antico, obsoleto e inefficiente, non è più supportato e probabilmente presenta una serie di buchi di sicurezza non corretti. Sito ufficiale di controllo delle versioni di Postgres.
@David ha già fornito l'istruzione SQL.

3 e 4) Una violazione della chiave duplicata. PostgreSQL che genera un errore significa anche che l'intera transazione viene annullata. Catturarlo in uno script perl non può far passare il resto della transazione. Ad esempio, dovresti creare uno script lato server con plpgsql, in cui puoi rilevare le eccezioni.