sql >> Base de Datos >  >> RDS >> PostgreSQL

Cálculo y ahorro de espacio en PostgreSQL

"Columna Tetris"

De hecho, puedes hacer algo , pero esto necesita una comprensión más profunda. La palabra clave es relleno de alineación . Cada tipo de datos tiene requisitos de alineación específicos.

Puede minimizar el espacio perdido por el relleno entre columnas ordenándolos favorablemente. El siguiente ejemplo (extremo) desperdiciaría mucho espacio en el disco físico:

CREATE TABLE t (
    e int2    -- 6 bytes of padding after int2
  , a int8
  , f int2    -- 6 bytes of padding after int2
  , b int8
  , g int2    -- 6 bytes of padding after int2
  , c int8
  , h int2    -- 6 bytes of padding after int2
  , d int8)

Para guardar 24 bytes por fila, use en su lugar:

CREATE TABLE t (
    a int8
  , b int8
  , c int8
  , d int8
  , e int2
  , f int2
  , g int2
  , h int2)   -- 4 int2 occupy 8 byte (MAXALIGN), no padding at the end

db<>violín aquí
Sqlfiddle antiguo

Como regla general, si coloca columnas de 8 bytes primero, luego columnas de 4 bytes, 2 bytes y 1 byte al final, no puede equivocarse.

boolean , uuid (!) y algunos otros tipos no necesitan relleno de alineación. text , varchar y otros tipos "varlena" (longitud variable) nominalmente requieren alineación "int" (4 bytes en la mayoría de las máquinas). Pero no observé ningún relleno de alineación en el formato de disco (a diferencia de la RAM). Eventualmente, encontré la explicación en una nota en el código fuente:

Tenga en cuenta también que permitimos que se viole la alineación nominal al almacenar varlenas "empaquetadas"; el mecanismo TOAST se encarga de ocultar eso de la mayoría del código.

Por lo tanto, la alineación "int" solo se aplica cuando el dato (posiblemente comprimido) que incluye un solo byte de longitud principal supera los 127 bytes. Luego, el almacenamiento de varlena cambia a cuatro bytes principales y requiere alineación "int".

Normalmente, puede ahorrar un par de bytes por fila en el mejor de los casos jugando "column tetris" . Nada de esto es necesario en la mayoría de los casos. Pero con miles de millones de filas, puede significar fácilmente un par de gigabytes.

Puede probar el tamaño real de columna/fila con la función pg_column_size() .
Algunos tipos ocupan más espacio en RAM que en disco (formato comprimido o "empaquetado"). Puede obtener mejores resultados para las constantes (formato RAM) que para las columnas de la tabla cuando prueba el mismo valor (o una fila de valores frente a una fila de la tabla) con pg_column_size() .

Finalmente, algunos tipos se pueden comprimir o "tostar" (almacenar fuera de línea) o ambos.

Gastos generales por tupla (fila)

4 bytes por fila para el identificador de elemento, no sujeto a las consideraciones anteriores.
Y al menos 24 bytes (23 + relleno) para el encabezado de tupla. El manual sobre diseño de página de base de datos:

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, un campo de ID de objeto opcional y los datos del usuario.

Para el relleno entre el encabezado y los datos del usuario, debe saber MAXALIGN en su servidor, normalmente 8 bytes en un sistema operativo de 64 bits (o 4 bytes en un sistema operativo de 32 bits). Si no está seguro, consulte pg_controldata .

Ejecute lo siguiente en su directorio binario de Postgres para obtener una respuesta definitiva:

./pg_controldata /path/to/my/dbcluster

El manual:

Los datos reales del usuario (columnas de la fila) comienzan en el desplazamiento indicado por t_hoff , que siempre debe ser múltiplo de MAXALIGN distancia para la plataforma.

Por lo tanto, normalmente obtiene el almacenamiento óptimo empaquetando datos en múltiplos de 8 bytes.

No hay nada que ganar en el ejemplo que publicaste . Ya está bien embalado. 2 bytes de relleno después del último int2 , 4 bytes al final. Podría consolidar el relleno a 6 bytes al final, lo que no cambiaría nada.

Gastos generales por página de datos

El tamaño de la página de datos suele ser de 8 KB. Algo de sobrecarga/hinchazón también en este nivel:los restos no son lo suficientemente grandes como para caber en otra tupla y, lo que es más importante, filas muertas o un porcentaje reservado con el FILLFACTOR ajuste.

Hay un par de otros factores a tener en cuenta para el tamaño del disco:

  • ¿Cuántos registros puedo almacenar en 5 MB de PostgreSQL en Heroku?
  • ¿No usar NULL en PostgreSQL todavía usa un mapa de bits NULL en el encabezado?
  • Configuración de PostgreSQL para rendimiento de lectura

¿Tipos de matriz?

Con una matriz escriba como estaba evaluando, agregaría 24 bytes de sobrecarga para el tipo. Además, los elementos de la matriz ocupan espacio como de costumbre. Nada que ganar allí.