En realidad es más complejo que eso.
El mapa de bits nulo necesita un bit por columna en la fila, redondeado a bytes completos. Está solo allí si la fila real incluye al menos un valor NULL y está totalmente asignada en ese caso. NOT NULL
restricciones no afectan directamente eso. (Por supuesto, si todos los campos de su tabla son NOT NULL
, nunca puede haber un mapa de bits nulo.)
El "encabezado de la tupla del montón" (por fila) tiene una longitud de 23 bytes. Los datos reales comienzan en un múltiplo de MAXALIGN
después de eso, que normalmente es de 8 bytes en el sistema operativo de 64 bits (4 bytes en el sistema operativo de 32 bits). Ejecute el siguiente comando desde el directorio binario PostgreSQL como root para obtener una respuesta definitiva:
./pg_controldata /path/to/my/dbcluster
En una instalación típica de Debian de PostgreSQL 9.3 que sería:
sudo /usr/lib/postgresql/9.3/bin/pg_controldata /var/lib/postgresql/9.3/main
De cualquier manera, hay una libre byte entre el encabezado y el inicio alineado de los datos, que el mapa de bits nulo puede utilizar. Siempre y cuando su tabla tenga 8 columnas o menos, el almacenamiento NULL es efectivamente totalmente gratuito (en lo que respecta al espacio en disco).
Después de eso, otro MAXALIGN
(normalmente 8 bytes) se asigna para el mapa de bits nulo (más relleno) para cubrir otros 64 campos (normalmente). Etc.
Esto es válido para al menos las versiones 8.4 - 9.6 y lo más probable es que no cambie.
"un bit por columna en la fila, redondeado a bytes completos" parece estar en desacuerdo con "Después de eso, se asigna otro MAXALIGN (4/8 bytes)". ¿Es el verdadero sentido de esto "redondeado al próximo límite MAXALIGN"? –
@ChrisBetti: Es realmente como lo describo. El mapa de bits en sí mismo se redondea a bytes completos. Es por eso que puede caber en el 1 byte entre el encabezado de la tupla y el inicio de los datos de la fila para <= 8 columnas. Pero debido a los requisitos de alineación (los datos de fila deben comenzar en múltiples de 'MAXALIGN'), el espacio se asigna en múltiplos de' MAXALIGN' bytes después de eso. La diferencia se pierde en * relleno *. –
¿Qué sucede si hay 8 columnas y luego se agrega otra columna?¿Postgres tendrá que reescribir completamente la tabla para agregar el mapa de bits nulo de 8 bytes después del encabezado? – dtgq