Ci sono un paio di equivoci qui:
La bitmap nullo è non parte dell'intestazione mucchio tupla. Per documentazione:
Esiste un'intestazione di dimensioni fisse (che occupa 23 byte sulla maggior parte delle macchine), seguita da una bitmap null opzionale ...
Le tue 32 colonne nullable sono insospettabili per due motivi:
La bitmap null viene aggiunta per riga e solo se nella riga è presente almeno un NULL
valore effettivo . Le colonne nullable non hanno impatto diretto, ma solo i NULL
valori effettivi . Se la bitmap null è allocata, viene sempre allocata completamente (tutto o niente). La dimensione effettiva della bitmap null è 1 bit per colonna, arrotondata per eccesso al byte successivo . Per codice souce corrente:
#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
La bitmap null viene allocata dopo l'intestazione della tupla heap e seguita da un OID opzionale e quindi dai dati delle righe. L'inizio di un OID o dei dati di riga è indicato t_hoff
nell'intestazione. Codice sorgente per commento :
Nota che t_hoff deve essere un multiplo di MAXALIGN.
C'è un byte libero dopo l'intestazione della tupla heap, che occupa 23 byte. Pertanto, la bitmap null per righe fino a 8 colonne non ha costi aggiuntivi. Con la nona colonna nella tabella, t_hoff
vengono avanzati altri MAXALIGN
(in genere 8) byte per fornire altre 64 colonne. Quindi il prossimo bordo sarebbe a 72 colonne.
Per visualizzare le informazioni di controllo di un cluster di database PostgreSQL (incl. MAXALIGN
), Esempio per un'installazione tipica di Postgres 9.3 su una macchina Debian:
sudo /usr/lib/postgresql/9.3/bin/pg_controldata /var/lib/postgresql/9.3/main
Ho aggiornato le istruzioni nella relativa risposta che hai citato .
A parte questo, anche se la tua ALTER TABLE
dichiarazione innesca un'intera riscrittura di una tabella (cosa che probabilmente fa, cambiando un tipo di dati), 250K non sono poi così tanti e sarebbero una questione di secondi su qualsiasi macchina a metà decente (a meno che le righe non siano insolitamente grandi) . 10 minuti o più indicano un problema completamente diverso. La tua dichiarazione è in attesa di ottenere un lucchetto sul tavolo, molto probabilmente.
Il numero crescente di voci pg_stat_activity
indica transazioni più aperte: indica l'accesso simultaneo alla tabella (molto probabilmente) che deve attendere il completamento dell'operazione.
Alcuni scatti nel buio
Verifica l'eventuale presenza di un eccesso di tavolo, prova un metodo delicato VACUUM mytable
o più aggressivo VACUUM FULL mytable
, che potrebbe riscontrare gli stessi problemi di concorrenza, poiché questo modulo acquisisce anche un blocco esclusivo. Invece potresti provare pg_repack ...
Vorrei iniziare esaminando possibili problemi con indici, trigger, chiave esterna o altri vincoli, in particolare quelli che coinvolgono la colonna. Soprattutto un indice corrotto potrebbe essere coinvolto? Provali REINDEX TABLE mytable;
o DROP
tutti e aggiungili nuovamente dopo ALTER TABLE
nella stessa transazione .
Prova a eseguire il comando di notte o quando non c'è molto carico.
Un metodo a forza bruta sarebbe quello di interrompere l'accesso al server, quindi riprovare:
Senza essere in grado di fissarlo, l'aggiornamento alla versione corrente o all'imminente 9.4 in particolare potrebbe aiutare. Sono stati apportati numerosi miglioramenti per i tavoli di grandi dimensioni e per i dettagli di blocco. Ma se c'è qualcosa di rotto nel tuo DB, dovresti probabilmente capirlo prima.
SET NOT NULL
non modifica il tipo, aggiunge solo un vincolo, ma il vincolo deve essere verificato rispetto alla tabella e ciò richiede una scansione completa della tabella. 9.4 migliora alcuni di questi casi prendendo blocchi più deboli, ma è ancora piuttosto pesante.