Código de error 1117 Demasiadas columnas; MySQL-column-limit en la tabla

37

Tengo una tabla con 1699 columnas y cuando intento insertar más columnas obtengo,

Código de error: 1117. Demasiadas columnas

En esta tabla solo tengo 1000 filas. Para mí lo más importante es el número de columnas. ¿Hay alguna limitación en la mesa? Quiero crear 2000 columnas. ¿Es eso posible?

OH LA LA
fuente
22
Buen señor, para qué diablos. Esto huele a un diseño de base de datos increíblemente pobre. O tal vez está utilizando la herramienta incorrecta para el trabajo. Tal vez usted debe buscar en la normalización de bases de datos
Zoredache
12
Gire su monitor 90 grados. Más en serio, MySQL (o casi cualquier otro RDBMS) no está diseñado para ESAS columnas.
11
¿Y por qué 2000 sensores deberían conducir a 2000 columnas? Rediseña tu base de datos. Cree una tabla de sensores separada o algo así, pero NO agregue cada sensor como una nueva columna. Eso es algo increíblemente incorrecto que hacer.
66
Número máximo de mesa ... ¡vaya! Es probable que solo necesite un par de mesas. ¡Ni siquiera considere crear 2000 tablas en lugar de 2000 columnas!
2
¡Por favor, por favor, lea sobre la normalización de la base de datos !

Respuestas:

35

¿Por qué necesitarías crear una tabla con incluso 20 columnas, y mucho menos 2000?

Por supuesto, los datos desnormalizados pueden evitar tener que hacer JOIN para recuperar muchas columnas de datos. Sin embargo, si tiene más de 10 columnas, debe detenerse y pensar en lo que sucedería debajo del capó durante la recuperación de datos.

Si una tabla de 2000 columnas se somete a SELECCIONAR * DESDE ... DONDE, generaría grandes tablas temporales durante el procesamiento, recuperando columnas que son innecesarias y creando muchos escenarios en los que los paquetes de comunicación ( max_allowed_packet ) serían llevados al límite en cada consulta.

En mis primeros días como desarrollador, trabajé en una empresa en 1995, donde DB2 era el RDBMS principal. La compañía tenía una sola tabla que tenía 270 columnas, docenas de índices y problemas de rendimiento al recuperar datos. Se pusieron en contacto con IBM y pidieron a los consultores que revisaran la arquitectura de su sistema, incluida esta tabla monolítica. Se le dijo a la compañía "Si no normaliza esta tabla en los próximos 2 años, DB2 fallará en las consultas que realicen el Proceso Stage2 (cualquier consulta que requiera la clasificación en columnas no indexadas)". Esto se le dijo a una compañía multimillonaria para normalizar una tabla de 270 columnas. Cuánto más que una tabla de 2000 columnas.

En términos de mysql, tendría que compensar el mal diseño estableciendo opciones comparables al procesamiento de DB2 Stage2. En este caso, esas opciones serían

Ajustar estas configuraciones para compensar la presencia de docenas, y mucho menos cientos, de columnas funciona bien si tiene TB de RAM.

Este problema se multiplica geométricamente si usa InnoDB, ya que tendrá que lidiar con MVCC (Control de concurrencia multiversional) que intenta proteger toneladas de columnas con cada SELECCIONAR, ACTUALIZAR y ELIMINAR mediante el aislamiento de transacciones.

CONCLUSIÓN

No hay sustituto o curita que pueda compensar el mal diseño. Por favor, por el bien de tu cordura en el futuro, ¡normaliza esa mesa hoy!

RolandoMySQLDBA
fuente
1
Me imaginaba cómo le iría a la compañía cuando le dijeran esto. Agregan ganchos svn o crean "directrices de mejores prácticas de base de datos" pidiendo a los desarrolladores que no clasifiquen columnas no indexadas en SQL. En cambio, hacen la clasificación dentro de la aplicación implementando su propio algoritmo de clasificación de datos grandes.
Gqqnbig
25

Tengo problemas para imaginar algo donde el modelo de datos pueda contener legítimamente 2000 columnas en una tabla correctamente normalizada.

Supongo que probablemente esté haciendo algún tipo de esquema denormalizado de "rellenar los espacios en blanco", donde en realidad está almacenando todo tipo de datos en una sola tabla, y en lugar de dividir los datos en tablas separadas y establecer relaciones , tiene varios campos que registran qué "tipo" de datos se almacena en una fila determinada, y el 90% de sus campos son NULL. Incluso entonces, sin embargo, querer llegar a 2000 columnas ... vaya.

La solución a su problema es repensar su modelo de datos. Si está almacenando una gran cantidad de datos clave / valor asociados con un registro dado, ¿por qué no modelarlo de esa manera? Algo como:

CREATE TABLE master (
    id INT PRIMARY KEY AUTO_INCREMENT,
    <fields that really do relate to the
    master records on a 1-to-1 basis>
);

CREATE TABLE sensor_readings (
    id INT PRIMARY KEY AUTO_INCREMENT,
    master_id INT NOT NULL,   -- The id of the record in the
                              -- master table this field belongs to
    sensor_id INT NOT NULL,
    value VARCHAR(255)
);

CREATE TABLE sensors (
    id INT PRIMARY KEY AUTO_INCREMENT,
    <fields relating to sensors>
);

Luego, para obtener todas las entradas de sensor asociadas con un registro "maestro" dado, puede simplemente SELECT sensor_id,value FROM sensor_readings WHERE master_id=<some master ID>. Si necesita obtener los datos para un registro en la mastertabla junto con todos los datos del sensor para ese registro, puede usar una combinación:

SELECT master.*,sensor_readings.sensor_id,sensor_readings.value
FROM master INNER JOIN sensor_readings on master.id=sensor_readings.master_id
WHERE master.id=<some ID>

Y luego se une más si necesita detalles de cada sensor.

womble
fuente
18

Es un sistema de medición con 2000 sensores.

Ignore todos los comentarios que gritan sobre la normalización: lo que está pidiendo podría ser un diseño de base de datos razonable (en un mundo ideal) y perfectamente normalizado, es muy inusual y, como se señaló en otra parte, los RDBMS generalmente no están diseñados para estas columnas. .

Aunque no está alcanzando el límite estricto de MySQL , uno de los otros factores mencionados en el enlace probablemente le impide subir más

Como otros sugieren, podría evitar esta limitación al tener una tabla secundaria con id, sensor_id, sensor_value, o más simplemente, podría crear una segunda tabla para contener solo las columnas que no encajarían en la primera (y usar la misma PK)

Jack Douglas
fuente
1
Esto es verdad. Al manejar los datos y el SQL correspondiente con gran cuidado, su respuesta se destaca aún más.
RolandoMySQLDBA
3
Usar una tabla secundaria no es una "solución". Tener una columna para cada sensor es simplemente un diseño malo (incorrecto). Es como tener una columna para cada empleado en un sistema de recursos humanos, o una columna para cada fabricante de automóviles para un DB que gestiona los modelos de automóviles.
a_horse_with_no_name
11
@a_horse: está haciendo suposiciones que dudo que sean válidas. Es muy posible que el número de sensores sea básicamente fijo, que todos se lean simultáneamente y que todos devuelvan datos cada vez. En cuyo caso, una columna por sensor no está "mal", simplemente no es práctico dadas las limitaciones de la base de datos. Me gusta asumir que los interrogadores no son idiotas hasta que se demuestre lo contrario e iUngi ha respondido con dignidad frente a las respuestas muy inútiles de la multitud de SF.
Jack Douglas
2
@Jack Douglas: incluso si todas esas suposiciones tuyas fueran ciertas (lo cual dudo mucho) almacenar cada valor de sensor en su propia columna causará problemas a largo plazo. ¿Qué pasa con consultas como "cuál es el valor promedio para los sensores 10 a 50 y 25 a 100 entre ayer y hoy"? o "¿Qué sensor tuvo el valor de lectura más alto el lunes pasado?". Intenta escribir consultas para esto con 2000 columnas. El uso de una tabla normalizada resolverá más problemas a largo plazo que la solución de 2000 columnas resolverá ahora.
a_horse_with_no_name
2
Claro, si los sensores almacenan valores relacionados, supongo que no están relacionados (por ejemplo, todos miden diferentes tipos de cosas en lugar de básicamente lo mismo en diferentes lugares). Puede dudarlo, pero solo el OP lo sabe con certeza, y no es imposible en los campos médicos o científicos.
Jack Douglas
15

Límites de conteo de columnas de MySQL 5.0 (énfasis agregado):

Hay un límite estricto de 4096 columnas por tabla , pero el máximo efectivo puede ser menor para una tabla determinada. El límite exacto depende de varios factores que interactúan.

  • Cada tabla (independientemente del motor de almacenamiento) tiene un tamaño máximo de fila de 65.535 bytes. Los motores de almacenamiento pueden imponer restricciones adicionales en este límite, reduciendo el tamaño máximo efectivo de fila.

    El tamaño máximo de fila restringe el número (y posiblemente el tamaño) de columnas porque la longitud total de todas las columnas no puede exceder este tamaño.

...

Los motores de almacenamiento individuales pueden imponer restricciones adicionales que limitan el recuento de columnas de la tabla. Ejemplos:

  • InnoDB permite hasta 1000 columnas.
lg_
fuente
7

Primero un poco más de llamas, luego una solución real ...

Principalmente estoy de acuerdo con las llamas que ya te arrojaron.

No estoy de acuerdo con la normalización clave-valor. Las consultas terminan siendo horribles; rendimiento aún peor.

Una forma 'simple' de evitar el problema inmediato (limitación del número de columnas) es 'particionar verticalmente' los datos. Tener, digamos, 5 tablas con 400 columnas cada una. Todos tendrían la misma clave primaria, excepto que uno podría ser AUTO_INCREMENT.

Quizás sea mejor decidir sobre la docena de campos que son más importantes, ponerlos en la tabla 'principal'. Luego, agrupe los sensores de manera lógica y colóquelos en varias tablas paralelas. Con la agrupación adecuada, es posible que no tenga que UNIRSE a todas las tablas todo el tiempo.

¿Estás indexando alguno de los valores? ¿Necesitas buscar en ellos? ¿Probablemente buscas en fecha y hora?

Si necesita indexar muchas columnas, punt.

Si necesita indexar algunos, colóquelos en la 'tabla principal.

Aquí está la solución real (si corresponde) ...

Si no necesita la gran variedad de sensores indexados, ¡no haga columnas! Si, me escuchaste. En su lugar, recójalos en JSON, comprima el JSON, guárdelo en un campo BLOB. Ahorrará una tonelada de espacio; solo tendrá una tabla, sin problemas de límite de columna; etc. Su aplicación se descomprimirá y luego usará el JSON como estructura. ¿Adivina qué? Puede tener estructura: puede agrupar los sensores en matrices, material multinivel, etc., tal como le gustaría a su aplicación. Otra 'característica' es abierta. Si agrega más sensores, no necesita ALTERAR la tabla. JSON si flexible de esa manera.

(La compresión es opcional; si su conjunto de datos es enorme, ayudará con el espacio en disco, por lo tanto, el rendimiento general).

Rick James
fuente
Esta es la mejor respuesta real. Está bien comentar que tal vez debería investigar no tener tantas columnas, pero que la respuesta aceptada sea 'no hagas eso' no responde la pregunta. Incluso si este tipo realmente no necesita tantas columnas, tal vez alguien más que encuentre esta Q sí lo necesita y necesita una respuesta real.
BoB3K
@ BoB3K: mi párrafo grande dice qué hacer , dada la información disponible sobre el problema como se indicó. JSONevita las "demasiadas columnas"; indexar columnas seleccionadas ayuda con el rendimiento.
Rick James
3

Veo esto como un posible escenario en el mundo de Big Data, donde es posible que no esté realizando el tipo tradicional de consultas select *. Nos ocupamos de esto en el mundo del modelado predictivo a nivel de cliente, donde modelamos un cliente en miles de dimensiones (todas ellas con valores de 0 o 1). Esta forma de almacenamiento facilita las actividades de creación de modelos posteriores, etc., cuando tiene los factores de riesgo en la misma fila y el indicador de resultado en la misma fila también. Esto puede normalizarse desde un punto de almacenamiento con una estructura padre-hija, pero El modelo predictivo aguas abajo deberá convertirlo nuevamente en un esquema plano. Usamos el desplazamiento hacia el rojo que almacena columnas, por lo que sus más de 1000 columnas cuando carga los datos, en realidad se almacenan en un formato de columnas ...

Hay un momento y lugar para este diseño. Absolutamente. La normalización no es la solución para cada problema.

BigDataGuy
fuente
Gracias por el comentario. Si se desea realizar análisis con imágenes, incluso una pequeña imagen en color de 16x16 píxeles requiere 16 * 16 * 3 enteros entre 0 y 255 (3 números para describir el color en uno de 16x16 píxeles con colores RGB). Eso es 768 columnas solo para datos, a las que uno debería agregar una clave.
VictorZurkowski