¿Un valor de columna vacía ocupa el mismo espacio de almacenamiento que un valor de columna lleno?

15

Tengo una mesa con 2 columnas. El tipo de ambas columnas está establecido en varchar(38). Si creo una fila con un valor vacío para una de las columnas, ¿ocupará el mismo espacio de almacenamiento que si el valor no estuviera vacío?

En otras palabras, ¿MySQL reservará espacio de almacenamiento para la columna (dependiendo de su tipo) cuando se cree una fila?

Haris ur Rehman
fuente

Respuestas:

11

Desde la estructura de filas físicas de Innodb, viñeta # 7 bajo REDUNDANT ROW_FORMAT

Un valor NULL de SQL reserva uno o dos bytes en el directorio de registros. Además de eso, un valor SQL NULL reserva cero bytes en la parte de datos del registro si se almacena en una columna de longitud variable . En una columna de longitud fija, reserva la longitud fija de la columna en la parte de datos del registro. Reservar el espacio fijo para valores NULL permite que se realice una actualización de la columna de NULL a un valor no NULL sin causar fragmentación de la página de índice.

Desde la estructura de filas físicas de Innodb, viñeta # 2 bajo COMPACT ROW_FORMAT

La parte de longitud variable del encabezado del registro contiene un vector de bits para indicar columnas NULL. Si el número de columnas en el índice que puede ser NULL es N, el vector de bits ocupa bytes CEILING (N / 8) . (Por ejemplo, si hay entre 9 y 15 columnas que pueden ser NULL, el vector de bits usa dos bytes). Las columnas que son NULL no ocupan espacio que no sea el bit en este vector . La parte de longitud variable del encabezado también contiene las longitudes de las columnas de longitud variable. Cada longitud toma uno o dos bytes, dependiendo de la longitud máxima de la columna. Si todas las columnas del índice NO SON NULAS y tienen una longitud fija, el encabezado del registro no tiene una parte de longitud variable.

En base a estos puntos de viñeta, esto es lo que ocupa un NULLvalor para el almacenamiento de una columna

  • longitud variable: un valor NULL no ocupa almacenamiento en la fila misma
  • longitud fija: ocupa el espacio reservado

Ahora, debe decidir entre usar CHAR y VARCHAR debido a lo que trajo el primer punto

Reservar el espacio fijo para valores NULL permite realizar una actualización de la columna de NULL a un valor que no sea NULL sin causar fragmentación de la página de índice.

Esto evitará la introducción de cualquier fragmentación de una fila en el camino una vez que se almacenen datos no NULL. Esto es algo que he discutido antes con respecto a MyISAM: vea mi publicación anterior ¿Cuál es el impacto en el rendimiento del uso de CHAR vs VARCHAR en un campo de tamaño fijo? .

RolandoMySQLDBA
fuente
Hola Rolando, había otro elemento que olvidé mencionar, la diferencia en la asignación de memoria entre una declaración de tipo varchar (5) y varchar (100). O realmente la pena incurrida por la sobreasignación.
Craig Efrein
@CraigEfrein Definitivamente debe agregar la asignación de memoria que a su respuesta. (Por cierto, ya he votado tu respuesta)
RolandoMySQLDBA
1
La penalización por sobreasignación ocurre cuando tiene un complejo SELECTque necesita crear una tabla temporal. Si es posible, usará MEMORYy convertirá VARCHARa CHARpara la tabla tmp. Ahora VARCHAR(100)toma unos 100 (o 300) bytes fijos, lo que posiblemente ralentiza la consulta.
Rick James
@RolandoMySQLDBA, ¿El comportamiento explicado en su respuesta se aplica a los formatos de fila Mysql 5.7 DYNAMIC y COMPACT?
Dinesh Kumar
@DineshKumar Estos párrafos todavía están en los documentos 5.7 / 8.0. Consulte dev.mysql.com/doc/refman/5.7/en/innodb-row-format-dynamic.html para DYNAMIC.
RolandoMySQLDBA
8

Independientemente de la longitud que defina para su columna varchar, el espacio de almacenamiento utilizado por una columna vacía será el mismo.

Los tipos CHAR y VARCHAR

ingrese la descripción de la imagen aquí

Esto solo aborda el espacio utilizado por la columna varchar y no considera el espacio de almacenamiento total utilizado por la fila, sus índices, claves primarias y otras columnas.

Como ypercube menciona en su comentario, hay consideraciones adicionales para el almacenamiento de filas en su conjunto cuando al menos una columna anulable está presente.

Estructura de fila física de Innodb

La parte de longitud variable del encabezado del registro contiene un vector de bits para indicar columnas NULL. Si hay entre 9 y 15 columnas que pueden ser NULL, el vector de bits usa dos bytes).

...

La parte de longitud variable del encabezado también contiene las longitudes de las columnas de longitud variable. Cada longitud toma uno o dos bytes, dependiendo de la longitud máxima de la columna. Si todas las columnas del índice NO SON NULAS y tienen una longitud fija, el encabezado del registro no tiene una parte de longitud variable

Y sí, el espacio de almacenamiento utilizado cambia según el tipo que elija, es fijo o variable, la clasificación y otros factores, como el motor.

MySQL hace recomendaciones para optimizar el almacenamiento de datos aquí: Optimización del tamaño de datos

Actualizar

Una consideración adicional con varchar y eso es memoria. Es importante en MySQL limitar el tamaño de una columna de longitud variable tanto como sea posible. Aunque la columna es variable y el espacio de almacenamiento utilizado es variable, MySQL asignará memoria en fragmentos fijos para almacenar valores. Por ejemplo, varchar (200) usará más memoria que varchar (5). Este no es un problema de espacio de almacenamiento, pero aún es algo a considerar al definir sus columnas.

Craig Efrein
fuente
Los números anteriores suponen CHARACTER SETlatin1 o ascii. Para utf8, el almacenamiento requerido CHAR(4)es 12.
Rick James