Code d'erreur 1117 Trop de colonnes; MySQL colonne-limite sur la table


38

J'ai une table avec 1699 colonnes et quand j'essaye d'insérer plus de colonnes, je reçois,

Code d'erreur: 1117. Trop de colonnes

Dans ce tableau je n'ai que 1000 lignes. Pour moi, le plus important est le nombre de colonnes. Y a-t-il des limites sur la table? Je veux créer 2000 colonnes. Est-ce possible?


22
Bon dieu, pourquoi diable? Cela sent une conception de base de données incroyablement pauvre. Ou peut-être que vous utilisez le mauvais outil pour le travail. Peut-être devriez-vous vous intéresser à la normalisation de la base
Zoredache le

12
Faites pivoter votre moniteur de 90 degrés. Plus sérieusement, MySQL (ou presque n'importe quel autre SGBDR) n'est pas conçu pour QUE beaucoup de colonnes.

11
Et pourquoi 2000 capteurs devraient-ils conduire à 2000 colonnes? Reconcevoir votre base de données. Créez une table de capteurs séparée ou quelque chose d'autre, mais N'Ajoutez PAS chaque capteur dans une nouvelle colonne. C'est incroyablement une mauvaise chose à faire.

6
Nombre maximum de tables ... whoa là! Vous n'aurez probablement besoin que de quelques tables. N'envisagez même pas de créer 2 000 tables au lieu de 2 000 colonnes!

2
S'il vous plaît, s'il vous plaît, s'il vous plaît lire sur la normalisation de la base de données !

Réponses:


36

Pourquoi auriez-vous besoin de créer une table avec même 20 colonnes, sans parler de 2000 ???

Les données dénormalisées accordées peuvent éviter d'avoir à faire des jointures pour extraire plusieurs colonnes de données. Toutefois, si vous avez plus de 10 colonnes, vous devriez vous arrêter et penser à ce qui se passerait sous le capot lors de la récupération des données.

Si une table de 2 000 colonnes subit SELECT * FROM ... WHERE, vous devez générer de grandes tables temporaires pendant le traitement, extraire des colonnes inutiles et créer de nombreux scénarios dans lesquels les paquets de communication ( max_allowed_packet ) sont poussés à la limite de chaque requête.

Lorsque j'étais développeur, je travaillais dans une entreprise en 1995, où DB2 était le principal SGBDR. La société ne disposait que d’une seule table comportant 270 colonnes, ainsi que de dizaines d’index, et rencontrait des problèmes de performances lors de la récupération des données. Ils ont contacté IBM et des consultants ont examiné l'architecture de leur système, y compris cette table monolithique. "Si vous ne normalisez pas cette table au cours des deux prochaines années, DB2 échouera pour les requêtes exécutant Stage2 Processing (toutes les requêtes nécessitant un tri sur des colonnes non indexées)". Cela a été dit à une entreprise de plusieurs milliards de dollars, pour normaliser un tableau de 270 colonnes. Combien plus une table de colonne 2000.

En termes de mysql, vous devrez compenser cette mauvaise conception en définissant des options comparables à celles de DB2 Stage2 Processing. Dans ce cas, ces options seraient

Modifier ces paramètres pour compenser la présence de dizaines, et encore moins de centaines de colonnes, fonctionne bien si vous avez des To de RAM.

Ce problème se multiplie géométriquement si vous utilisez InnoDB car vous devrez traiter avec MVCC (Multiversion Concurrency Control) en essayant de protéger des tonnes de colonnes avec chaque SELECT, UPDATE et DELETE par l’isolement de transaction.

CONCLUSION

Il n'y a pas de substitut ou de pansement qui puisse compenser une mauvaise conception. S'il vous plaît, pour votre santé mentale à l'avenir, normalisez cette table aujourd'hui !!!


1
Je pouvais imaginer ce que ferait la société quand on le lui dirait. Ils ajoutent svn hooks ou créent des "directives de meilleures pratiques en matière de base de données" demandant aux développeurs de ne pas trier les colonnes non indexées en SQL. Au lieu de cela, ils effectuent le tri au sein de l'application en implémentant leur propre algorithme de tri de données volumineux.
Gqqnbig

25

J'ai du mal à imaginer quoi que ce soit dont le modèle de données pourrait légitimement contenir 2 000 colonnes dans un tableau correctement normalisé.

Mon hypothèse est que vous êtes probablement en train de créer une sorte de schéma dénormalisé «remplissez les espaces», dans lequel vous stockez en fait toutes sortes de données dans une seule table, au lieu de les décomposer en plusieurs tables et de créer des relations. , vous avez différents champs qui enregistrent quel "type" de données est stocké dans une ligne donnée, et 90% de vos champs sont NULL. Même dans ce cas, vouloir atteindre 2000 colonnes ... beurk.

La solution à votre problème consiste à repenser votre modèle de données. Si vous stockez une grande quantité de données clés / valeurs associées à un enregistrement donné, pourquoi ne pas les modéliser de cette manière? Quelque chose comme:

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>
);

Ensuite, vous pouvez simplement obtenir toutes les entrées de capteur associées à un enregistrement "principal" donné SELECT sensor_id,value FROM sensor_readings WHERE master_id=<some master ID>. Si vous devez obtenir les données d'un enregistrement dans la mastertable avec toutes les données de capteur pour cet enregistrement, vous pouvez utiliser une jointure:

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>

Et ensuite, rejoint si vous avez besoin de détails sur ce que chaque capteur est.


18

C'est un système de mesure avec 2000 capteurs

Ignorez tous les commentaires sur la normalisation - ce que vous demandez pourrait être une conception de base de données raisonnable (dans un monde idéal) et parfaitement normalisée. C'est tout à fait inhabituel et, comme indiqué ailleurs, les SGBDR ne sont généralement pas conçus pour autant de colonnes. .

Bien que vous n'ayez pas atteint la limite stricte de MySQL , l'un des autres facteurs mentionnés dans le lien vous empêche probablement d'aller plus haut.

Comme le suggèrent d'autres personnes, vous pouvez contourner cette limitation en disposant une table enfant avec id, sensor_id, sensor_value, ou plus simplement, vous pouvez créer une seconde table pour ne contenir que les colonnes qui ne rentreront pas dans la première (et utiliser le même PK).


1
C'est vrai. Lorsque vous manipulez les données et le code SQL correspondant avec beaucoup de soin, votre réponse se démarque encore plus !!!
RolandoMySQLDBA

3
L'utilisation d'une table enfant n'est pas une "solution de contournement". Avoir une colonne pour chaque capteur est tout simplement mauvais (mauvais). Cela revient à avoir une colonne pour chaque employé dans un système de ressources humaines ou une colonne pour chaque constructeur de voiture pour une base de données gérant des modèles de voiture.
a_horse_with_no_name

11
@a_horse - vous faites des hypothèses qui, je doute, sont valables. Il est fort possible que le nombre de capteurs soit fondamentalement fixe, que tous soient lus simultanément et que tous renvoient des données à chaque fois. Dans ce cas, une colonne par capteur n’est pas "fausse", mais peu pratique compte tenu des limites de la base de données. J'aime supposer que les questionneurs ne sont pas des idiots jusqu'à preuve du contraire et iUngi a répondu avec dignité face à des réponses très inutiles de la part de la foule des FS.
Jack Douglas

2
@ Jack Douglas: même si toutes vos hypothèses étaient vraies (ce dont je doute fort), le stockage de chaque valeur de capteur dans sa propre colonne causera des problèmes à long terme. Qu'en est-il des requêtes telles que "quelle est la valeur moyenne pour les capteurs 10 à 50 et 25 à 100 entre hier et aujourd'hui"? ou "Quel capteur avait la valeur de lecture la plus élevée lundi dernier?". Essayez d'écrire des requêtes pour cela avec 2000 colonnes. L'utilisation d'une table normalisée résoudra plus de problèmes à long terme que la solution à 2 000 colonnes ne résoudra plus maintenant.
a_horse_with_no_name

2
Bien sûr, si les capteurs stockent des valeurs liées - je suppose qu’ils ne sont pas liés (par exemple, ils mesurent tous des choses différentes plutôt que la même chose à des endroits différents). Vous en douterez peut-être, mais seul le PO en est certain - et ce n’est pas impossible dans les domaines médical ou scientifique.
Jack Douglas

15

Nombre de colonnes dans MySQL 5.0 (emphase ajoutée):

Il existe une limite fixe de 4096 colonnes par table , mais le maximum effectif peut être inférieur pour une table donnée. La limite exacte dépend de plusieurs facteurs en interaction.

  • Chaque table (quel que soit le moteur de stockage) a une taille de ligne maximale de 65 535 octets. Les moteurs de stockage peuvent imposer des contraintes supplémentaires à cette limite, réduisant ainsi la taille maximale effective de la ligne.

    La taille maximale de la ligne limite le nombre (et éventuellement la taille) des colonnes car la longueur totale de toutes les colonnes ne peut pas dépasser cette taille.

...

Les moteurs de stockage individuels peuvent imposer des restrictions supplémentaires limitant le nombre de colonnes de la table. Exemples:

  • InnoDB autorise jusqu'à 1000 colonnes.

7

D'abord un peu plus flamboyant, ensuite une vraie solution ...

Je suis surtout d'accord avec les flammes déjà lancées sur vous.

Je ne suis pas d'accord avec la normalisation des valeurs-clés. Les requêtes finissent par être horribles; performance encore pire.

Un moyen "simple" d'éviter le problème immédiat (limitation du nombre de colonnes) consiste à "partitionner verticalement" les données. Disons, par exemple, 5 tables de 400 colonnes chacune. Ils auraient tous la même clé primaire, sauf que l'un d'entre eux pourrait être AUTO_INCREMENT.

Il serait peut-être préférable de choisir la douzaine de champs les plus importants et de les placer dans le tableau principal. Regroupez ensuite les capteurs de manière logique et mettez-les dans plusieurs tables parallèles. Avec le regroupement approprié, vous ne serez peut-être pas obligé de JOIN toutes les tables tout le temps.

Êtes-vous en train d'indexer certaines des valeurs? Avez-vous besoin de chercher sur eux? Vous recherchez probablement sur datetime?

Si vous avez besoin d'indexer beaucoup de colonnes - punt.

Si vous devez en indexer quelques-uns, mettez-les dans la table principale.

Voici la vraie solution (si elle s'applique) ...

Si vous n'avez pas besoin de la vaste gamme de capteurs indexés, ne créez pas de colonnes! Oui, tu m'as entendu Au lieu de cela, collectez-les dans JSON, compressez-le, stockez-le dans un champ BLOB. Vous allez économiser une tonne d'espace; vous aurez une seule table, avec pas de problèmes de limite de colonne; etc. Votre application se décompressera, puis utilisera le JSON comme structure. Devine quoi? Vous pouvez avoir une structure - vous pouvez regrouper les capteurs dans des tableaux, des éléments multiniveaux, etc., tout comme votre application le souhaiterait. Une autre "fonctionnalité" - il est ouvert. Si vous ajoutez d'autres capteurs, vous n'avez pas besoin de modifier le tableau. JSON si flexible de cette façon.

(La compression est facultative. Si votre jeu de données est énorme, cela vous aidera avec de l'espace disque, donc des performances globales.)


C'est la meilleure réponse réelle. Il est normal de dire qu'il devrait peut-être faire une recherche pour ne pas avoir autant de colonnes, mais la réponse acceptée, qui est «ne le fais pas», ne répond pas à la question. Même si ce gars-là n'a pas vraiment besoin de tant de colonnes, peut-être que quelqu'un d'autre découvrant que Q a besoin de tant de colonnes et a besoin d'une vraie réponse.
BoB3K

@ BoB3K - Mon grand paragraphe dit quoi faire , étant donné les informations disponibles sur le problème, comme indiqué. JSONévite les "trop ​​de colonnes"; l'indexation des colonnes sélectionnées contribue à la performance.
Rick James

3

Je vois cela comme un scénario possible dans le monde des données volumineuses, où vous n’effectuerez peut-être pas le type classique de requêtes select *. Nous traitons cela dans le monde de la modélisation prédictive au niveau client, où nous modélisons un client à travers des milliers de dimensions (toutes ayant une valeur de 0 ou 1). Ce mode de stockage facilite les activités de construction de modèles en aval, etc., lorsque les facteurs de risque se trouvent dans la même ligne et le résultat dans la même ligne. Ceci peut être normalisé à partir d'un point de vue de stockage avec une structure parent le modèle prédictif en aval devra le reconvertir en schéma plat. Nous utilisons redshift pour le stockage en colonnes. Ainsi, vos 1000 colonnes et plus lorsque vous chargez les données sont réellement stockées dans un format en colonnes ...

Il y a un moment et un endroit pour cette conception. Absolument. La normalisation n'est pas la solution à tous les problèmes.


Merci pour le commentaire. Si vous souhaitez effectuer des analyses avec des images, même une petite image couleur de 16x16 pixels nécessite 16 * 16 * 3 entiers compris entre 0 et 255 (3 chiffres décrivant la couleur dans un des 16x16 pixels en utilisant des couleurs RVB). Il s’agit de 768 colonnes réservées aux données, auxquelles il faudrait ajouter une clé.
VictorZurkowski
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.