prefacio
El artículo anterior decía que InnoDB tiene Compact
, Redundant
, Dynamic
y Compressed4
formatos de fila. Habla principalmente del Compact
formato de fila, que se compone de dos partes principales: información adicional registrada y datos reales registrados. Se recomienda leer el artículo anterior y el artículo anterior. Si es importante Diga [ through train ] tres veces, no se salte el capítulo. Hoy entendemos principalmente los tres formatos de fila restantes y el desbordamiento de datos de fila
Tabla de contenido
1. Formato de fila redundante
El formato de fila redundante es un formato de fila utilizado antes de MySQL 5.0, lo que significa que es muy antiguo, pero aún quiero mencionarlo desde la perspectiva del aprendizaje, y todos pueden entenderlo.El formato de fila redundante como se muestra en la imagen:
Para un mejor aprendizaje, creamos una demo3
tabla aquí y agregamos dos datos
mysql> create table demo3( c1 varchar(10), c2 varchar(10) not null, c3 char(10), c4 varchar(10), c5 varchar(1024)) charset=ascii row_format=Redundant;
Query OK, 0 rows affected (0.02 sec)
mysql> insert into demo3 values('aaaaa','bbbb','ccc','dd','e');
Query OK, 1 row affected (0.00 sec)
mysql> insert into demo3 values('eeeee','ffff',null,null,'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdeefghijklmnopqrstuvwxyz');
Query OK, 1 row affected (0.00 sec)
Los registros en la tabla ahora se ven así
mysql> select * from demo3;
+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------+
| c1 | c2 | c3 | c4 | c5 |
+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------+
| aaaaa | bbbb | ccc | dd | e |
| eeeee | ffff | NULL | NULL | abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz |
+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
Echemos un vistazo a las diferencias en el formato de línea redundante desde varios aspectos.
1.1 Lista de compensaciones de longitud de campo
Compact
El comienzo del formato de línea es una lista de longitud de campo de longitud variable, y Redundant
el comienzo del formato de línea es una lista de desplazamiento de longitud de campo, que es diferente de la lista de longitud de campo de longitud variable de dos maneras:
- No hay
变长
dos palabras, es decir, el formato de fila redundante almacenará la información de longitud de todas las columnas (incluidas las columnas ocultas) en el registro en orden inverso a la lista de compensación de longitud de campo - Hay dos
偏移
palabras más, lo que significa que el método de cálculo de la longitud es diferente del formato de fila compacto, que no es tan intuitivo, utiliza la diferencia entre números adyacentes para calcular la longitud de cada columna.
Por ejemplo, la primera fila de datos, intentemos analizarla:
La longitud de la primera columna row_id
es de 6 bytes, es decir, la longitud de 0x06
la segunda columna trx_id
es de 6 bytes, un total de 12 bytes, es decir, la longitud de 0x0c
la tercera columna roll_pointer
es de 7 bytes, un total de 19 bytes, también Eso es decir, la longitud de 0x13
la cuarta columna C1
es de 5 bytes, un total de 24 bytes, es decir, la longitud de 0x18
la quinta columna C2
es de 4 bytes, un total de 28 bytes, es decir, la longitud de 0x1c
la sexta columna C3
es de 10 bytes, Un total de 38 bytes, es decir, la longitud de 0x26
la séptima columna C4
es de 2 bytes, un total de 40 bytes, es decir, la longitud de 0x28
la octava columna C5
es de 1 byte, un total de 41 bytes, es decir0x29
El efecto de la descarga de orden inverso es: 29 28 26 1c 18 13 0c 06
, complete los datos como se muestra en la figura
Abrimos directamente demo3.ibd
el archivo para verlo
1.2 Información del encabezado del registro
La información del encabezado del registro en formato de fila redundante consiste en bytes 6 y bits binarios 48. Los significados de estos bits binarios son los siguientes:
nombre | tamaño (unidad: bit) | describir |
---|---|---|
bit reservado 1 | 1 | no utilizado |
reservado 2 | 1 | no utilizado |
eliminar_mascarilla | 1 | Marcar si se elimina el registro |
min_rec_mask | 1 | Esta marca se agregará al registro más pequeño en cada nodo que no sea hoja del árbol B+ |
n_propiedad | 4 | Indica el número de registros que posee el registro actual |
heap_no | 13 | Indica la información de posición del registro actual en el montón de registros |
n_campo | 10 | Indica el número de columnas en el registro |
1byte_offs_bandera | 1 | Si el desplazamiento correspondiente a cada columna en la lista de desplazamiento de longitud de campo de etiqueta está representado por 1 byte o 2 bytes |
próximo_registro | dieciséis | Indica la posición relativa del siguiente registro |
La primera línea de información del encabezado del registro es:00 00 10 11 00 ca
Convirtamos el registro anterior de hexadecimal a binario e intentemos analizarlo.
00000000 00000000 00010000 00010001 00000000 11001010
De acuerdo con estos datos binarios, la siguiente información se puede obtener dividiendo los datos de acuerdo con la estructura del encabezado del registro
Bit reservado 1: 0
Bit reservado 2: 0
delete_mask: 0
min_rec_mask: 0
n_owned: 0000
heap_no: 00000000 00010 (2)
n_field: 000 0001000 (8)
1byte_offs_flag: 1 (1)
next_record: 00000000 1100101 0 (202)
En comparación con la información del encabezado del registro en el formato de línea compacta, existen dos diferencias:
- El formato de fila redundante tiene dos atributos más: n_field y 1byte_offs_flag;
- El formato de fila redundante no tiene el atributo record_type.
1.4 Cómo elegir el valor de 1byte_offs_flag
Dijimos anteriormente que el desplazamiento correspondiente a cada columna puede ocupar 1 byte o 2 bytes para el almacenamiento, entonces, ¿cuándo usar 1 byte y cuándo usar 2 bytes? De hecho, se juzga según el tamaño total de los datos reales registrados en el formato de fila Redundante:
-
Cuando el número de bytes que ocupan los datos reales registrados es menor o igual a 127 (hexadecimal 0x7f, binario 01111111), el desplazamiento correspondiente a cada columna ocupa 1 byte
-
Cuando el número de bytes que ocupan los datos reales registrados es superior a 127 pero no superior a 32767 (hexadecimal 0x7fff, binario 0111111111111111), el desplazamiento correspondiente a cada columna ocupa 2 bytes
-
Cuando los datos reales del registro son mayores a 32767, el registro en este momento se ha almacenado en la página de desbordamiento, y solo los primeros 768 bytes y la dirección de la página de desbordamiento de 20 bytes están reservados en esta página (por supuesto, en estos 20 bytes También se registra otra información). Debido a que la lista de compensación de longitud de campo solo necesita registrar la compensación de cada columna en esta página, es suficiente que cada columna use 2 bytes para almacenar la compensación.
Para saber si el desplazamiento de cada columna está representado por 1 byte o 2 bytes al analizar registros, el formato de fila redundante coloca deliberadamente un atributo llamado 1byte_offs_flag en la información del encabezado del registro:
- Cuando su valor es 1, indica que se utiliza 1 byte para el almacenamiento
- Cuando su valor es 0, indica que se utilizan 2 bytes para el almacenamiento
1.5 Manejo de valores NULL en el formato de fila Redundante
Debido a que el formato de fila redundante no tiene una lista de valores NULL, el formato de fila redundante realiza un procesamiento especial en los desplazamientos correspondientes a cada columna en la lista de desplazamiento de longitud de campo: el primer bit del valor de desplazamiento correspondiente a la columna Como base si es NULL, este bit también puede denominarse bit NULL. Es decir, al analizar una columna de un registro, primero verifique si el bit NULL del desplazamiento correspondiente a la columna es 1, si es 1, entonces el valor de la columna es NULL, de lo contrario, no es NULL.
Esto también explica por qué siempre que el dato real registrado anteriormente sea mayor a 127 (hexadecimal 0x7f, binario 01111111), se utilizan 2 bytes para representar el desplazamiento correspondiente a una columna, principalmente el primer bit es el llamado bit NULL, utilizado para marcar si el valor de la columna es NULL.
Pero hay otro punto a tener en cuenta, para una columna con un valor NULL, si el tipo de columna es un tipo de longitud fija determina el método de almacenamiento real del valor NULL:
- Si el campo que almacena el valor NULL es de tipo de longitud fija, como el tipo de datos CHAR(M), el valor NULL también ocupará la parte de datos reales del registro, y los datos correspondientes a este campo se completarán con 0x00 bytes. .
- Si el campo que almacena el valor NULL es de tipo de datos de longitud variable, no se ocupará ningún espacio de almacenamiento en los datos reales del registro.
Además de los puntos anteriores, el formato de línea redundante y el formato de línea compacta son aproximadamente iguales
Intentemos analizar el segundo dato (el número de bytes que ocupan los datos reales es superior a 127):
La longitud de la primera columna row_id
es de 6 bytes, es decir, la longitud de 0x00 0x06
la segunda columna trx_id
es de 6 bytes, un total de 12 bytes, es decir, la longitud de 0x00 0x0c
la tercera columna roll_pointer
es de 7 bytes, un total de 19 bytes, también Eso es decir, la longitud de 0x00 0x13
la cuarta columna C1
es de 5 bytes, un total de 24 bytes, es decir, la longitud de 0x00 0x18
la quinta columna C2
es de 4 bytes, un total de 28 bytes, es decir, la longitud de 0x00 0x1c
la sexta columna C3
es de 10 bytes, Un total de 38 bytes, es decir 0x00 0x26
, pero el valor es NULL, 最高位标识1
después de eso, el valor de 0x80 0x26
la séptima columna C4
es NULL, un total de 38 bytes, es decir, la longitud de 0x80 0x26
la octava columna C5
es de 130 bytes, un total de 168 Festival de personajes, es decir0x00 0xa8
Abrimos directamente el archivo demo3.ibd para ver si es correcto:
Además de los puntos anteriores, el formato de línea redundante y el formato de línea compacta son aproximadamente iguales.
1.6 Formato de almacenamiento de la columna CHAR(M)
Sabemos que el formato de fila Compacto es bastante problemático cuando se almacenan datos en columnas de tipo CHAR(M), se divide en juegos de caracteres de longitud variable y juegos de caracteres de longitud fija, pero es muy simple en el formato de fila Redundante, independientemente de los caracteres utilizados en la columna ¿Cuál es el conjunto, siempre que se utilice el tipo CHAR(M), el espacio de datos real ocupado es el producto del número máximo de bytes requerido por el conjunto de caracteres para representar un carácter y M. Por ejemplo, el espacio de datos real ocupado por una columna de tipo CHAR(10) que usa el juego de caracteres utf8 siempre es de 30 bytes, y el espacio de datos real ocupado por una columna de tipo CHAR(10) que usa el juego de caracteres gbk es siempre de 20 bytes. Se puede ver a partir de esto que la columna de tipo CHAR(M) que usa el formato de fila Redundante no generará fragmentación.
2. Desbordamiento de datos de fila
2.1 Los datos máximos que VARCHAR(M) puede almacenar
Sabemos que una columna de tipo VARCHAR(M) puede ocupar hasta 65535 bytes. Entre ellos, M representa el número máximo de caracteres almacenados en este tipo.Si usamos el conjunto de caracteres ASCII, un carácter representa un byte.Veamos si VARCHAR(65535) está disponible
mysql> create table demo4 (c varchar(65535)) charset=ascii row_format=compact;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
Se puede ver en el mensaje de error que MySQL tiene un límite en el espacio de almacenamiento máximo ocupado por un registro. Excepto por columnas de tipo BLOB o TEXT, los bytes ocupados por todas las demás columnas (excluyendo columnas ocultas e información de encabezado de registro) El total la longitud no puede exceder los 65535 bytes. Entonces, el servidor MySQL sugiere que cambiemos el tipo de almacenamiento a TEXT o BLOB. Además de los datos de la columna en sí, estos 65535 bytes también incluyen algunos otros datos (sobrecarga de almacenamiento).Por ejemplo, para almacenar una columna de tipo VARCHAR(M), en realidad necesitamos ocupar 3 partes de espacio de almacenamiento:
- datos reales
- Los datos reales ocupan la longitud del byte (pueden ocupar dos bits)
- Identificación de valor NULL, si la columna no tiene el atributo NOT NULL (un bit), solo se pueden almacenar 65532 bytes de datos como máximo
mysql> create table demo4 (c varchar(65532)) charset=ascii row_format=compact;
Query OK, 0 rows affected (0.06 sec)
Si la columna de tipo VARCHAR(M) no utiliza el conjunto de caracteres ASCII, el valor máximo de M depende del número máximo de bytes requerido por el conjunto de caracteres para representar un carácter. En el caso de que se permita que el valor de la columna sea NULL, el juego de caracteres gbk indica que un carácter requiere como máximo 2 bytes, luego, bajo este juego de caracteres, el valor máximo de M es 32766 (es decir: 65532/2) , es decir Puede almacenar hasta 32766 caracteres, el juego de caracteres utf8 significa que un carácter necesita hasta 3 bytes, por lo que bajo este juego de caracteres, el valor máximo de M es 21844, lo que significa que puede almacenar hasta 21844 ( es decir: 65532/3) carácter.
2.2 Desbordamiento causado por demasiados datos en el registro
Hagamos una prueba con ascii
una demo4
tabla de conjuntos de caracteres e insertemos un dato:
mysql> insert into demo4 values(repeat('a',65532));
Query OK, 1 row affected (0.02 sec)
Sugerencia:
REPEAT('a', 65532) es una llamada de función, lo que significa generar una cadena que repite el carácter 'a' 65532 veces
Como se mencionó anteriormente, la unidad básica de interacción entre el disco y la memoria en MySQL es la página, es decir, MySQL usa la página como la unidad básica para administrar el espacio de almacenamiento, y nuestros registros se asignarán a una determinada página para su almacenamiento. El tamaño de una página es generalmente de 16 KB, que son 16384 bytes, y un VARCHAR(M)
tipo de columna puede almacenar hasta 65532 bytes, lo que puede causar una situación embarazosa en la que una página no puede almacenar un registro.
En los formatos de fila Compacto y Reduntante, para una columna que ocupa un gran espacio de almacenamiento, solo una parte de los datos de la columna se almacenarán en los datos reales del registro, y los datos restantes se dispersarán y almacenarán en varios otros. páginas, y luego los datos reales del registro. El lugar de datos utiliza 20 bytes para almacenar las direcciones que apuntan a estas páginas (por supuesto, estos 20 bytes también incluyen el número de bytes ocupados por los datos dispersos en otras páginas), de modo que el Se puede encontrar la página donde se encuentran los datos restantes, como la que se muestra en la figura:
Como se puede ver en la figura, para los formatos de fila Compacto y Reduntante, si hay muchos datos en una columna, solo los primeros 768 bytes de datos en la columna y un puntero a otras columnas se almacenarán en los datos reales de este registro. La dirección de la página, y luego almacenar los datos restantes en otras páginas. Este proceso también se denomina desbordamiento de página, y aquellas páginas que almacenan más de 768 bytes también se denominan páginas de desbordamiento.
Finalmente, debe tenerse en cuenta que no solo las columnas de tipo VARCHAR(M), sino también las columnas de otros tipos TEXT y BLOB se desbordarán al almacenar una gran cantidad de datos.
Tres, el punto crítico de desbordamiento de línea.
¿Cuál es el punto crítico donde ocurre el desbordamiento de fila? En otras palabras, el desbordamiento de filas ocurre cuando la columna almacena ¿cuántos bytes de datos?
MySQL estipula que se deben almacenar al menos dos filas de registros en una página. Además de almacenar nuestros registros, cada página también necesita almacenar información adicional. La información extra desordenada debe agregar hasta 132 bytes de espacio (ahora solo necesito saber este número. ok), el resto del espacio se puede usar para almacenar registros.
La información adicional requerida para cada registro es de 27 bytes.
- 2 bytes se utilizan para almacenar la longitud de los datos reales
- 1 byte se usa para almacenar si la columna es un valor NULL
- 5 bytes de información de encabezado
- 6 bytes para la columna DB_ROW_ID
- 6 bytes para la columna DB_TRX_ID
- 7 bytes para la columna DB_ROLL_PTR
Suponiendo que el número de bytes de datos almacenados en una columna es n, MySQL estipula que si la columna no se desborda, debe satisfacer la siguiente fórmula:
132 + 2×(27 + n) < 16384
Resolviendo esta fórmula se obtiene la solución: n < 8099. Es decir, si los datos almacenados en una columna tienen menos de 8099 bytes, la columna no se convertirá en una columna de desbordamiento; de lo contrario, la columna deberá convertirse en una columna de desbordamiento. Sin embargo, la conclusión de 8099 bytes es solo para una demo4
tabla con una sola columna. Si hay varias columnas en la tabla, la fórmula anterior y la conclusión deben cambiarse, por lo que el punto es: no necesita prestar atención a este crítico Cuál es el punto, solo sepa que si los datos almacenados en una columna de nuestro registro ocupan muchos bytes, la columna puede convertirse en una columna de desbordamiento.
Formato de cuatro líneas, DINÁMICO y COMPRIMIDO
A continuación, se presentarán los otros dos formatos de fila Dynamic
y Compressed
el formato de fila. La versión de MySQL que estoy usando ahora es 8.0 y su formato de fila predeterminado es Dinámico.
mysql> show variables like '%innodb_default_row_format%';
+---------------------------+---------+
| Variable_name | Value |
+---------------------------+---------+
| innodb_default_row_format | dynamic |
+---------------------------+---------+
1 row in set (0.04 sec)
mysql> set persist innodb_default_row_format = 'dynamic';
Query OK, 0 rows affected (0.01 sec)
Estos dos formatos de línea son similares al formato de línea compacto, pero son un poco diferentes cuando se trata de datos de desbordamiento de fila. No almacenarán los primeros 768 bytes de los datos reales del campo en los datos reales del registro, sino que almacenarán todos los bytes Todos se almacenan en otras páginas, y solo las direcciones de otras páginas se almacenan en los datos reales registrados.
La diferencia entre el formato de fila comprimido y dinámico es que el formato de fila comprimido utiliza un algoritmo de compresión para comprimir la página y ahorrar espacio.
Resumir
Estos dos artículos tienen mucho conocimiento teórico, jaja, pero afortunadamente no se usan mucho en el trabajo, es bueno que todos conozcan estos términos, porque en la explicación de MVCC más adelante, también usaremos algunos términos profesionales en este artículo InnoDB define 4 formatos de fila, y la estructura de registro de cada formato de fila es diferente. Al mismo tiempo, también hemos aprendido sobre los métodos de almacenamiento de tipos de datos de longitud fija y variable en la estructura de registro y el desbordamiento de fila. Vamos concluir
-
La página es la unidad básica de interacción entre disco y memoria en MySQL, y también la unidad básica de MySQL para administrar el espacio de almacenamiento.
-
InnoDB actualmente define formatos de 4 filas:
- Formato de fila COMPACTO:
- Formato de fila REDUNDANTE:
-
Formatos de fila DINÁMICA y COMPRIMIDA:
Los formatos de fila Dinámico y Comprimido son similares al formato de fila COMPACTO, y son un poco diferentes cuando se trata de datos de desbordamiento de fila. No almacenan los primeros 768 bytes de los datos reales del campo en los datos reales del registro, pero almacenan todos los bytes Para otras páginas, solo almacene la dirección de otras páginas en los datos reales del registro
- Formato de fila COMPACTO:
-
Formato de fila COMPACTO Para columnas de tipo CHAR(M), cuando la columna utiliza un conjunto de caracteres de longitud fija, el número de bytes ocupados por la columna no se agregará a la lista de longitud de campo de longitud variable, y si la longitud variable se utiliza el conjunto de caracteres, el número de bytes ocupados por la columna también se agregará a la lista de longitud de campo de longitud variable.
-
En el caso de que se permita que el valor de la columna sea NULL, el valor máximo de M bajo el juego de caracteres gbk es 32766, y el valor máximo de M bajo el juego de caracteres utf8 es 21844. Todo esto es solo en el caso de un campo en la tabla ¡Asegúrese de recordar que la longitud total de bytes ocupados por todas las columnas en una fila (excluyendo las columnas ocultas y la información del encabezado del registro) no puede exceder los 65535 bytes!
-
Cuando hay demasiados datos en el registro y no caben en la página actual, los datos sobrantes se almacenarán en otras páginas.Este fenómeno se denomina desbordamiento de fila. En los formatos de fila Compacto y Redundante, para columnas que ocupan un gran espacio de almacenamiento, solo una parte de los datos de la columna se almacenará en los datos reales registrados, y los datos restantes se dispersarán y almacenarán en varias otras páginas, y luego, los 20 bytes de datos reales registrados se utilizan para almacenar direcciones que apuntan a estas páginas.
-
El punto crítico del desbordamiento de fila: si los datos almacenados en una columna tienen menos de 8099 bytes, entonces la columna no se convertirá en una columna de desbordamiento; de lo contrario, la columna debe ser una columna de desbordamiento. Sin embargo, la conclusión de 8099 bytes es solo para una tabla con una sola columna. Si hay varias columnas en la tabla, la conclusión será inconsistente, por lo que el punto es: no es necesario que preste atención a cuál es el punto crítico. Es decir, solo sepa que si cuando los datos almacenados en una columna de un registro ocupan una cantidad muy alta de bytes, la columna puede convertirse en una columna de desbordamiento.
-
Las columnas del tipo CHAR(M) del juego de caracteres de longitud variable requieren al menos M bytes, mientras que VARCHAR(M) no tiene este requisito. Por ejemplo, para una columna CHAR(10) que utiliza el conjunto de caracteres utf8, la longitud de los datos almacenados en la columna oscila entre 10 y 30 bytes. Incluso si almacenamos una cadena vacía en esta columna, ocupará 10 bytes. Esto se debe a que la longitud en bytes del valor actualizado en el futuro es mayor que la longitud en bytes del valor original y menos de 10 bytes. El registro es actualizado directamente en lugar de reasignar un nuevo espacio de registro en el espacio de almacenamiento, lo que hace que el espacio de registro original se convierta en la denominada fragmentación
Cuando terminé de aprender esta parte del conocimiento, admiré la profundidad de la investigación del autor, aunque los puntos del conocimiento son muchos, difíciles y complicados, la forma en que el autor combina imágenes y textos nos permite entenderlo bien.
Hasta ahora, el estudio de hoy ha terminado, espero que te conviertas en un yo indestructible
~~~
No puedes conectar los puntos mirando hacia adelante; solo puedes conectarlos mirando hacia atrás. Así que tienes que confiar en que los puntos se conectarán de alguna manera en tu futuro. Tienes que confiar en algo: tu instinto, destino, vida, karma, lo que sea. Este enfoque nunca me ha defraudado y ha marcado una gran diferencia en mi vida.
Si mi contenido te es útil, por favor 点赞
, 评论
,, 收藏
la creación no es fácil, el apoyo de todos es la motivación para que yo persevere