Fehlercode 1117 Zu viele Spalten; MySQL-Spaltenlimit für Tabelle

37

Ich habe eine Tabelle mit 1699 Spalten und wenn ich versuche, mehr Spalten einzufügen, erhalte ich

Fehlercode: 1117. Zu viele Spalten

In dieser Tabelle habe ich nur 1000 Zeilen. Für mich ist die Anzahl der Spalten das Wichtigste. Gibt es irgendwelche Einschränkungen auf dem Tisch? Ich möchte 2000 Spalten erstellen. Ist das möglich?

OHLÁLÁ
quelle
21
Guter Herr, wofür zum Teufel. Dies riecht nach einem wahnsinnig schlechten Datenbankdesign. Oder Sie verwenden das falsche Werkzeug für den Job. Vielleicht sollten Sie sich die Datenbanknormalisierung
ansehen
12
Drehen Sie Ihren Monitor um 90 Grad. Im Ernst, MySQL (oder fast jedes andere RDBMS) ist nicht für DIESE vielen Spalten ausgelegt.
11
Und warum sollten 2000 Sensoren zu 2000 Spalten führen? Gestalten Sie Ihre Datenbank neu. Erstellen Sie eine separate Sensortabelle oder ähnliches, fügen Sie jedoch NICHT jeden Sensor als neue Spalte hinzu. Das ist einfach unglaublich falsch.
6
Maximale Tischanzahl ... whoa da! Sie werden wahrscheinlich nur ein paar Tische brauchen. Ziehen Sie nicht einmal in Betracht, 2000 Tabellen anstelle von 2000 Spalten zu erstellen!
2
Bitte, bitte, bitte lesen Sie über Datenbanknormalisierung !

Antworten:

35

Warum müssten Sie eine Tabelle mit sogar 20 Spalten erstellen, geschweige denn 2000 ???

Zugegeben, denormalisierte Daten können verhindern, dass JOINs ausgeführt werden müssen, um viele Datenspalten abzurufen. Wenn Sie jedoch über 10 Spalten verfügen, sollten Sie anhalten und überlegen, was beim Abrufen von Daten unter der Haube passieren würde.

Wenn für eine 2000-Spaltentabelle SELECT * FROM ... WHERE ausgeführt wird, werden während der Verarbeitung große temporäre Tabellen generiert, unnötige Spalten abgerufen und viele Szenarien erstellt, in denen Kommunikationspakete ( max_allowed_packet ) bei jeder Abfrage an den Rand gedrängt werden.

In meinen früheren Tagen als Entwickler arbeitete ich 1995 in einem Unternehmen, in dem DB2 das wichtigste RDBMS war. Das Unternehmen verfügte über eine einzige Tabelle mit 270 Spalten, Dutzenden von Indizes und Leistungsproblemen beim Abrufen von Daten. Sie setzten sich mit IBM in Verbindung und ließen die Berater die Architektur ihres Systems überprüfen, einschließlich dieser einen monolithischen Tabelle. Der Firma wurde mitgeteilt, "Wenn Sie diese Tabelle in den nächsten zwei Jahren nicht normalisieren, schlägt DB2 bei Abfragen fehl, die Stage2-Verarbeitung ausführen (alle Abfragen, die eine Sortierung nach nicht indizierten Spalten erfordern)." Dies wurde einer Multi-Billionen-Dollar-Firma mitgeteilt, um eine 270-Spalten-Tabelle zu normalisieren. Wie viel mehr als eine 2000-Spalten-Tabelle.

In Bezug auf MySQL müssten Sie ein derart schlechtes Design ausgleichen, indem Sie Optionen festlegen, die mit DB2 Stage2 Processing vergleichbar sind. In diesem Fall wären diese Optionen

Das Tweeten dieser Einstellungen, um das Vorhandensein von Dutzenden, geschweige denn Hunderten von Spalten auszugleichen, funktioniert gut, wenn Sie über TB RAM verfügen.

Dieses Problem vervielfacht sich geometrisch, wenn Sie InnoDB verwenden, da Sie sich mit MVCC (Multiversion Concurrency Control) befassen müssen , um Tonnen von Spalten mit jedem SELECT, UPDATE und DELETE durch Transaktionsisolation zu schützen.

FAZIT

Es gibt keinen Ersatz oder Pflaster, der ein schlechtes Design ausgleichen könnte. Bitte normalisieren Sie diese Tabelle noch heute, damit Sie in Zukunft gesund werden !!!

RolandoMySQLDBA
quelle
1
Ich konnte mir vorstellen, wie sich das Unternehmen verhalten würde, wenn man es mir sagt. Sie fügen svn-Hooks hinzu oder erstellen "DB-Best-Practice-Richtlinien", in denen Entwickler aufgefordert werden, nicht indizierte Spalten in SQL nicht zu sortieren. Stattdessen sortieren sie innerhalb der Anwendung, indem sie ihren eigenen Algorithmus zum Sortieren großer Datenmengen implementieren.
Gqqnbig
25

Ich habe Probleme, mir irgendetwas vorzustellen, bei dem das Datenmodell legitimerweise 2000 Spalten in einer ordnungsgemäß normalisierten Tabelle enthalten könnte.

Ich vermute, dass Sie wahrscheinlich eine Art denormalisiertes "Lücken füllen" -Schema ausführen, in dem Sie tatsächlich alle verschiedenen Arten von Daten in einer Tabelle speichern und stattdessen die Daten in separate Tabellen aufteilen und Beziehungen herstellen Sie haben verschiedene Felder, die aufzeichnen, welcher "Datentyp" in einer bestimmten Zeile gespeichert ist, und 90% Ihrer Felder sind NULL. Aber auch dann, um auf 2000 Kolonnen zu kommen ... yikes.

Die Lösung für Ihr Problem besteht darin, Ihr Datenmodell zu überdenken. Wenn Sie einen großen Stapel von Schlüssel- / Wertdaten speichern, die mit einem bestimmten Datensatz verknüpft sind, warum nicht auf diese Weise modellieren? So etwas wie:

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

Dann können Sie einfach alle Sensoreinträge abrufen, die mit einem bestimmten "Master" -Datensatz verknüpft sind SELECT sensor_id,value FROM sensor_readings WHERE master_id=<some master ID>. Wenn Sie die Daten für einen Datensatz in der masterTabelle zusammen mit allen Sensordaten für diesen Datensatz abrufen möchten, können Sie einen Join verwenden:

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>

Und dann kommen weitere hinzu, wenn Sie Details zu jedem Sensor benötigen.

womble
quelle
18

Es ist ein Messsystem mit 2000 Sensoren

Ignorieren Sie alle Kommentare zur Normalisierung - was Sie verlangen, ist möglicherweise ein vernünftiges Datenbankdesign (in einer idealen Welt), das perfekt normalisiert ist. Es ist nur sehr ungewöhnlich, und wie an anderer Stelle erwähnt, sind RDBMSs normalerweise einfach nicht für so viele Spalten konzipiert .

Obwohl Sie das MySQL- Hardlimit nicht einhalten , hindert einer der anderen im Link genannten Faktoren Sie wahrscheinlich daran, höher zu steigen

Wie andere empfehlen, können Sie diese Einschränkung umgehen, indem Sie eine untergeordnete Tabelle mit id, sensor_id, sensor_valueeiner zweiten Tabelle erstellen, die nur die Spalten enthält, die nicht in die erste passen (und dieselbe PK verwenden).

Jack Douglas
quelle
1
Das ist wahr. Beim sorgfältigen Umgang mit Daten und entsprechendem SQL fällt Ihre Antwort umso mehr auf !!!
RolandoMySQLDBA
3
Die Verwendung einer untergeordneten Tabelle ist keine "Problemumgehung". Eine Spalte für jeden Sensor zu haben, ist einfach ein schlechtes (falsches) Design. Das ist wie eine Spalte für jeden Mitarbeiter in einem HR-System oder eine Spalte für jeden Automobilhersteller für eine DB, die Automodelle verwaltet.
a_horse_with_no_name
11
@a_horse - Sie machen Annahmen, von denen ich bezweifle, dass sie gültig sind. Es ist durchaus möglich, dass die Anzahl der Sensoren im Grunde genommen festgelegt ist, dass alle gleichzeitig gelesen werden und jedes Mal Daten zurückgeben. In diesem Fall ist eine Spalte pro Sensor nicht "falsch", sondern angesichts der Einschränkungen der Datenbank nur unpraktisch. Ich gehe gerne davon aus, dass Fragesteller erst dann Idioten sind, wenn das Gegenteil bewiesen ist, und iUngi hat mit Würde reagiert, obwohl die SF-Masse sehr wenig hilfreiche Antworten gegeben hat.
Jack Douglas
2
@Jack Douglas: Selbst wenn all Ihre Annahmen zutreffen (was ich sehr bezweifle), wird das Speichern jedes Sensorwerts in einer eigenen Spalte auf lange Sicht Probleme verursachen. Was ist mit Abfragen wie "Was ist der Durchschnittswert für die Sensoren 10 bis 50 und 25 bis 100 zwischen gestern und heute?" oder "Welcher Sensor hatte letzten Montag den höchsten Messwert?". Versuchen Sie hierzu Abfragen mit 2000 Spalten zu schreiben. Die Verwendung einer normalisierten Tabelle löst auf lange Sicht mehr Probleme als die Lösung mit 2000 Spalten.
a_horse_with_no_name
2
Sicher, wenn die Sensoren verwandte Werte speichern - ich gehe davon aus, dass sie nicht verwandt sind (z. B. messen sie alle verschiedene Arten von Dingen und nicht im Grunde dasselbe an verschiedenen Orten). Sie mögen das bezweifeln, aber nur das OP weiß es mit Sicherheit - und es ist in medizinischen oder wissenschaftlichen Bereichen nicht unmöglich.
Jack Douglas
15

MySQL 5.0 Column-Count Limits (Hervorhebung hinzugefügt):

Es gibt ein festes Limit von 4096 Spalten pro Tabelle , aber das effektive Maximum kann für eine bestimmte Tabelle geringer sein. Die genaue Grenze hängt von mehreren Wechselwirkungsfaktoren ab.

  • Jede Tabelle (unabhängig von der Speicher-Engine) hat eine maximale Zeilengröße von 65.535 Byte. Speicher-Engines können diese Grenze zusätzlich einschränken und die effektive maximale Zeilengröße verringern.

    Die maximale Zeilengröße schränkt die Anzahl (und möglicherweise die Größe) der Spalten ein, da die Gesamtlänge aller Spalten diese Größe nicht überschreiten kann.

...

Einzelne Speicher-Engines können zusätzliche Einschränkungen festlegen, die die Anzahl der Tabellenspalten begrenzen. Beispiele:

  • InnoDB erlaubt bis zu 1000 Spalten.
lg_
quelle
7

Erst etwas mehr Flammen, dann eine echte Lösung ...

Ich stimme größtenteils mit den Flammen überein, die bereits auf dich geworfen wurden.

Ich bin mit der Schlüsselwertnormalisierung nicht einverstanden. Fragen sind schrecklich. Leistung noch schlimmer.

Eine "einfache" Möglichkeit, das unmittelbare Problem (Beschränkung der Spaltenanzahl) zu umgehen, besteht darin, die Daten vertikal zu partitionieren. Nehmen wir zum Beispiel 5 Tabellen mit jeweils 400 Spalten. Sie würden alle den gleichen Primärschlüssel haben, mit der Ausnahme, dass AUTO_INCREMENT derselbe sein könnte.

Vielleicht ist es besser, sich für ein Dutzend Felder zu entscheiden, die am wichtigsten sind, und sie in die Haupttabelle aufzunehmen. Gruppieren Sie dann die Sensoren auf logische Weise und ordnen Sie sie mehreren parallelen Tabellen zu. Mit der richtigen Gruppierung müssen Sie möglicherweise nicht immer alle Tabellen verbinden.

Indizieren Sie einen der Werte? Müssen Sie danach suchen? Wahrscheinlich suchen Sie nach Datum und Uhrzeit?

Wenn Sie viele Spalten indizieren müssen - punt.

Wenn Sie ein paar indizieren müssen, geben Sie sie in die Haupttabelle ein.

Hier ist die echte Lösung (falls zutreffend) ...

Wenn Sie nicht die große Anzahl von Sensoren indizieren müssen, machen Sie keine Spalten! Ja, du hast mich gehört. Sammeln Sie sie stattdessen in JSON, komprimieren Sie JSON, und speichern Sie sie in einem BLOB-Feld. Sie sparen eine Menge Platz; Sie haben nur eine Tabelle, bei der es keine Probleme mit Spaltenbeschränkungen gibt. usw. Ihre Anwendung wird dekomprimiert und verwendet dann JSON als Struktur. Erraten Sie, was? Sie können eine Struktur haben - Sie können die Sensoren in Arrays, Multilevel-Elemente usw. gruppieren, so wie es Ihre App möchte. Ein weiteres "Feature" - es ist unbefristet. Wenn Sie weitere Sensoren hinzufügen, müssen Sie die Tabelle nicht ÄNDERN. JSON ist auf diese Weise flexibel.

(Die Komprimierung ist optional. Wenn Ihr Dataset sehr umfangreich ist, hilft dies beim Speicherplatz und damit bei der Gesamtleistung.)

Rick James
quelle
Dies ist die aktuell beste Antwort. Es ist in Ordnung zu kommentieren, dass er vielleicht nachforschen sollte, wenn er nicht so viele Spalten hat, aber wenn die akzeptierte Antwort "Mach das nicht" lautet, wird die Frage nicht beantwortet. Auch wenn dieser Typ nicht wirklich so viele Spalten benötigt, braucht vielleicht jemand anderes, der dieses Q findet, so viele und braucht eine echte Antwort.
BoB3K
@ BoB3K - In meinem großen Absatz steht, was zu tun ist , wenn die verfügbaren Informationen zum Problem wie angegeben vorliegen. JSONvermeidet die "zu vielen Spalten"; Die Indizierung ausgewählter Spalten trägt zur Leistung bei.
Rick James
3

Ich betrachte dies als ein mögliches Szenario in der Welt der Big Data, in der Sie möglicherweise nicht den herkömmlichen Abfragetyp select * ausführen. Wir beschäftigen uns damit in der Welt der prädiktiven Modellierung auf Kundenebene, in der wir einen Kunden über Tausende von Dimensionen hinweg modellieren (alle mit Werten von 0 oder 1). Diese Art der Speicherung erleichtert die nachgelagerten Modellbildungstätigkeiten usw., wenn Sie die Risikofaktoren in derselben Zeile und das Ergebnis-Flag in derselben Zeile haben Das nachfolgende Vorhersagemodell muss es wieder in ein flaches Schema konvertieren. Wir verwenden Redshift für die Spaltenspeicherung, sodass Ihre über 1000 Spalten beim Laden der Daten tatsächlich in einem Spaltenformat gespeichert werden ...

Es gibt eine Zeit und einen Ort für dieses Design. Absolut. Normalisierung ist nicht die Lösung für jedes Problem.

BigDataGuy
quelle
Danke für den Kommentar. Wenn Sie Analysen mit Bildern durchführen möchten, sind für ein kleines Farbbild mit 16 x 16 Pixeln 16 * 16 * 3 Ganzzahlen zwischen 0 und 255 erforderlich (3 Zahlen zur Beschreibung der Farbe in einem von 16 x 16 Pixeln mithilfe von RGB-Farben). Das sind 768 Spalten nur für Daten, zu denen man einen Schlüssel hinzufügen müsste.
VictorZurkowski