2011-02-15 13 views

Respuesta

18

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.

+0

"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"? –

+0

@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 *. –

+0

¿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

3

El mapa de bits nulo sólo está presente si el bit HEAP_HASNULL se encuentra en t_infomask. Si está presente, comienza justo después del encabezado fijo y ocupa suficientes bytes para tener un bit por columna de datos (es decir, t_natts bits en total). En esta lista de bits, un bit de 1 indica que no es nulo, un bit de 0 es un valor nulo. Cuando el mapa de bits no está presente, se supone que todas las columnas no son nulas.

http://www.postgresql.org/docs/9.0/static/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE

por lo que para cada 8 columnas que usan un byte de almacenamiento adicional. Luego, por cada millón de filas que tomarían un megabyte de almacenamiento. Realmente no parece tan importante. Definiría las tablas cómo debían definirse y no me preocuparía por los encabezados nulos.