Aquí hay un par de malentendidos:
El mapa de bits nula es no parte de la cabecera montón tupla. Por documentación:
Hay un encabezado de tamaño fijo (que ocupa 23 bytes en la mayoría de las máquinas), seguido de un mapa de bits nulo opcional ...
Sus 32 columnas anulables no son sospechosas por dos razones:
El mapa de bits nulo se agrega por fila , y solo si hay al menos un NULL
valor real en la fila. Las columnas anulables no tienen impacto directo, solo los NULL
valores reales sí. Si se asigna el mapa de bits nulo, siempre se asigna completamente (todo o nada). El tamaño real del mapa de bits nulo es de 1 bit por columna, redondeado al siguiente byte . Por código de fuente actual:
#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
El mapa de bits nulo se asigna después del encabezado de la tupla de montón y seguido por un OID opcional y luego datos de fila. El inicio de un OID o datos de fila se indica mediante t_hoff
el encabezado. Por código fuente de comentario :
Tenga en cuenta que t_hoff debe ser un múltiplo de MAXALIGN.
Hay un byte libre después del encabezado de la tupla de montón, que ocupa 23 bytes. Por lo tanto, el mapa de bits nulo para filas de hasta 8 columnas efectivamente no tiene costo adicional. Con la novena columna de la tabla, t_hoff
se avanzan otros MAXALIGN
(normalmente 8) bytes para proporcionar otras 64 columnas. Entonces el próximo borde estaría en 72 columnas.
Para mostrar información de control de un clúster de base de datos PostgreSQL (incl. MAXALIGN
), Ejemplo para una instalación típica de Postgres 9.3 en una máquina Debian:
sudo /usr/lib/postgresql/9.3/bin/pg_controldata /var/lib/postgresql/9.3/main
Actualicé las instrucciones en la respuesta relacionada que usted citó .
Aparte de eso, incluso si su ALTER TABLE
declaración desencadena una reescritura de una tabla completa (lo que probablemente hace, cambiando un tipo de datos), 250K realmente no son tanto y serían cuestión de segundos en cualquier máquina medianamente decente (a menos que las filas sean inusualmente grandes) . 10 minutos o más indican un problema completamente diferente. Su estado de cuenta está esperando que se bloquee la mesa, muy probablemente.
El creciente número de entradas en pg_stat_activity
significa más transacciones abiertas: indica acceso concurrente en la tabla (muy probablemente) que tiene que esperar a que finalice la operación.
Algunas tomas en la oscuridad
Verifique la posible hinchazón de la tabla, pruebe con una suave VACUUM mytable
o más agresiva VACUUM FULL mytable
, que podría encontrar los mismos problemas de concurrencia, ya que este formulario también adquiere un bloqueo exclusivo. Podrías probar pg_repack en su lugar ...
Comenzaría por inspeccionar posibles problemas con índices, disparadores, claves foráneas u otras restricciones, especialmente las relacionadas con la columna. ¿Especialmente un índice dañado podría estar involucrado? Pruebe REINDEX TABLE mytable;
o DROP
todos ellos y vuelva a agregarlos después ALTER TABLE
de la misma transacción .
Intente ejecutar el comando en la noche o cuando no haya mucha carga.
Un método de fuerza bruta sería detener el acceso al servidor, luego intente nuevamente:
Sin poder precisarlo, la actualización a la versión actual o la próxima 9.4 en particular podría ayudar. Se han realizado varias mejoras para las mesas grandes y para los detalles de bloqueo. Pero si hay algo roto en su base de datos, probablemente debería resolverlo primero.
SET NOT NULL
no altera el tipo, solo agrega una restricción, pero la restricción debe verificarse contra la tabla, y eso requiere un escaneo completo de la tabla. 9.4 mejora algunos de estos casos al tomar bloqueos más débiles, pero sigue siendo bastante pesado.