InnoDB crea error de tabla: "Tamaño de fila demasiado grande"

11

Tenemos algunos ingenieros que aplanan una estructura db normalizada en una tabla temporal con el fin de generar un informe. Las columnas se especifican como TEXT NOT NULL(sé "¿por qué están haciendo eso?"; Supongamos que estamos abordando esto).

Utilizamos MySQL 5.1.48 Community RHEL5 con el complemento InnoDB 1.0.9 en Linux.

Cuando usamos MyISAM nunca encontramos límites de tamaño de tabla de columnas máximas o longitud máxima de fila (durante la investigación hemos alcanzado el límite máximo de columnas en 2598 (el 2599 causa el error 1117). Con InnoDB estamos alcanzando límites. Estos límites se manifiestan al crear el tabla (sin inserción de datos) como:

ERROR 1118 (42000) en la línea 1: tamaño de fila demasiado grande. El tamaño máximo de fila para el tipo de tabla utilizado, sin contar BLOB, es 8126. Debe cambiar algunas columnas a TEXTO o BLOB

Estoy buscando respuestas a lo siguiente:

  1. ¿Cuál es la fórmula detallada para determinar el tamaño de fila particularmente cuando se usan lotes de columnas v / v / b / t? He probado algunos formatos diferentes usando varchar(N)columnas (donde N está entre 1 y 512), el juego de caracteres UTF8 (* 3) y tantas columnas como la tabla tomará hasta el fallo. Ninguno de los combos que he intentado proporciona valores que coincidan con los resultados reales de la prueba.

  2. ¿Qué otra 'sobrecarga' debo considerar al calcular el tamaño de la fila?

  3. ¿Por qué el mensaje de error cambia de 8126 a 65535 cuando paso de crear tablas con columnas varchar (109) a columnas varchar (110)?


fuente
Yo tuve el mismo problema. Cuando estaba revisando una base de datos, encontré que uno de los complementos del navegador web estaba insertando el código html en el código fuente de la página (incluso en el formulario) y esto estaba causando el problema.
HTML no es el villano. Ni el tamaño de ese HTML. Debe haber tenido varias columnas de texto / varchar y haber alcanzado algunas limitaciones que se pueden solucionar.
Rick James

Respuestas:

19

Las respuestas a sus preguntas son complejas, ya que varían según el formato de archivo InnoDB . Hoy, hay dos formatos, llamados Antelope y Barracuda.

El archivo de espacio de tabla central (ibdata1) siempre está en formato Antelope . Si usa archivo por tabla, puede hacer que los archivos individuales usen el formato Barracuda configurando innodb_file_format=Barracudaen my.cnf.

Puntos básicos:

  • Una página de 16 KB de datos de InnoDB debe contener al menos dos filas de datos. Además, cada página tiene un encabezado y un pie de página que contiene sumas de verificación de página y número de secuencia de registro, etc. Ahí es donde obtienes tu límite de un poco menos de 8 KB por fila.

  • Los tipos de datos de tamaño fijo como INTEGER, DATE, FLOAT, CHAR se almacenan en esta página de datos primarios y cuentan para el límite de tamaño de fila.

  • Los tipos de datos de tamaño variable, como VARCHAR, TEXT, BLOB, se almacenan en páginas de desbordamiento, por lo que no cuentan totalmente para el límite de tamaño de fila. En Antelope, se almacenan hasta 768 bytes de tales columnas en la página de datos primarios además de almacenarse en la página de desbordamiento. Barracuda admite un formato de fila dinámico , por lo que puede almacenar solo un puntero de 20 bytes en la página de datos primaria.

  • Los tipos de datos de tamaño variable también tienen como prefijo 1 o más bytes para codificar la longitud. Y el formato de fila InnoDB también tiene una serie de desplazamientos de campo. Entonces, hay una estructura interna más o menos documentada en su wiki . [EDITAR] Enlace muerto: aquí se ve mejor ahora.

Barracuda también admite ROW_FORMAT = COMPRESSED para obtener una mayor eficiencia de almacenamiento para datos de desbordamiento.

También tengo que comentar que nunca he visto una tabla bien diseñada que supere el límite de tamaño de fila. Es un fuerte "olor a código" que estás violando la condición de grupos repetitivos de First Normal Form.

Bill Karwin
fuente
2
Es muy fácil para los ingenieros que no son conscientes de DB seguir la ruta de datos planos. NUNCA funciona. Mi propia base de datos heredada, que tiene una situación similar, no alcanza el tamaño de la fila, por lo que es menos dramática, ¡pero es una bendición de rendimiento! Diría que su ingeniero de informes debe aceptar que tendrán que hacer uniones y simplemente compensar ese trabajo con toda la indexación.
TechieGurl
1

Mi situación es un poco diferente. Uno de los elementos de datos que necesito almacenar en cada fila es potencialmente muy grande. (El campo de datos es un LONGBLOB para un documento que puede contener múltiples imágenes incrustadas. Mi base de datos de muestra contiene documentos de hasta 25-30 MB, pero estos documentos podrían ser más grandes en algunos casos). Ninguna de las soluciones que encontré en línea me proporcionó alivio. . (Cambió el tipo de archivo InnoDB a Barracuda, aumentó el tamaño del archivo de registro, configuró el formato de fila en COMPRIMIDO).

La única solución que he encontrado que me ha funcionado fue volver a MySQL 5.5.x desde MySQL 5.6.x.

David
fuente