it-swarm.com.de

Ist das Speichern einer begrenzten Liste in einer Datenbankspalte wirklich so schlecht?

Stellen Sie sich ein Webformular mit einer Reihe von Kontrollkästchen vor (eines oder alle davon können ausgewählt werden). Ich habe mich dafür entschieden, sie in einer durch Kommas getrennten Liste von Werten zu speichern, die in einer Spalte der Datenbanktabelle gespeichert sind.

Jetzt weiß ich, dass die richtige Lösung darin besteht, eine zweite Tabelle zu erstellen und die Datenbank ordnungsgemäß zu normalisieren. Es war schneller, die einfache Lösung zu implementieren, und ich wollte schnell und ohne großen Zeitaufwand einen Proof-of-Concept für diese Anwendung haben.

Ich dachte, die Zeitersparnis und der einfachere Code haben sich in meiner Situation gelohnt. Ist dies eine vertretbare Designwahl oder hätte ich sie von Anfang an normalisieren sollen?

Dies ist eine kleine interne Anwendung, die im Wesentlichen eine Excel-Datei ersetzt, die in einem freigegebenen Ordner gespeichert wurde. Ich frage auch, weil ich daran denke, das Programm zu bereinigen und es wartbarer zu machen. Es gibt einige Dinge, mit denen ich nicht ganz zufrieden bin. Eines davon ist das Thema dieser Frage.

342
Mad Scientist

Zusätzlich zum Verstoß gegen Erste Normalform aufgrund der sich wiederholenden Wertegruppe, die in einer einzelnen Spalte gespeichert ist, treten in durch Kommas getrennten Listen eine Reihe weiterer praktischerer Probleme auf:

  • Es kann nicht sichergestellt werden, dass jeder Wert den richtigen Datentyp aufweist: Keine Möglichkeit, 1,2,3, Banane, 5 zu verhindern.
  • Es können keine Fremdschlüsseleinschränkungen zum Verknüpfen von Werten mit einer Nachschlagetabelle verwendet werden. Keine Möglichkeit, die referenzielle Integrität durchzusetzen.
  • Eindeutigkeit kann nicht erzwungen werden: Keine Möglichkeit zu verhindern 1,2,3,3,3,5
  • Ein Wert kann nicht aus der Liste gelöscht werden, ohne die gesamte Liste abzurufen.
  • Eine Liste kann nicht länger gespeichert werden als in die Zeichenfolgenspalte passt.
  • Es ist schwierig, nach allen Entitäten mit einem bestimmten Wert in der Liste zu suchen. Sie müssen einen ineffizienten Tabellenscan verwenden. Möglicherweise müssen Sie auf reguläre Ausdrücke zurückgreifen, zum Beispiel in MySQL:
    idlist REGEXP '[[:<:]]2[[:>:]]'*
  • Schwer zu zählende Elemente in der Liste oder andere aggregierte Abfragen.
  • Es ist schwierig, die Werte mit der Nachschlagetabelle zu verknüpfen, auf die sie verweisen.
  • Es ist schwierig, die Liste in sortierter Reihenfolge abzurufen.

Um diese Probleme zu lösen, müssen Sie Tonnen von Anwendungscode schreiben und die Funktionen neu erfinden, die das RDBMS bereits wesentlich effizienter bereitstellt .

Kommagetrennte Listen sind so falsch, dass ich dies zum ersten Kapitel in meinem Buch gemacht habe: SQL-Antimuster: Vermeiden der Fallstricke der Datenbankprogrammierung .

Es gibt Zeiten, in denen Sie Denormalisierung anwenden müssen, aber wie @ OMG Ponies erwähnt , sind dies Ausnahmefälle. Jede nicht relationale „Optimierung“ kommt einem Abfragetyp zugute, der zu Lasten anderer Datennutzungen geht. Stellen Sie also sicher, dass Sie wissen, welche Ihrer Abfragen so speziell behandelt werden müssen, dass sie eine Denormalisierung verdienen.


* MySQL 8.0 unterstützt diese Word-Boundary-Ausdruckssyntax nicht mehr.

534
Bill Karwin

"Ein Grund war Faulheit".

Dies läutet Alarmglocken. Der einzige Grund, warum Sie so etwas tun sollten, ist, dass Sie wissen, wie man es "richtig" macht, aber Sie sind zu dem Schluss gekommen, dass es einen konkreten Grund gibt, es nicht so zu machen.

Allerdings: Wenn es sich bei den Daten, die Sie auf diese Weise speichern, um Daten handelt, nach denen Sie niemals eine Abfrage durchführen müssen, kann es sein, dass Sie sie in der von Ihnen gewählten Weise speichern.

(Einige Benutzer bestreiten die Aussage in meinem vorherigen Absatz mit der Aussage, dass "Sie nie wissen können, welche Anforderungen in Zukunft hinzugefügt werden". Diese Benutzer sind entweder irregeführt oder vertreten eine religiöse Überzeugung. Manchmal ist es vorteilhaft, an Ihren Anforderungen zu arbeiten habe vor dir.)

40
Hammerite

Es gibt zahlreiche Fragen zu SO fragen:

  • wie man eine Anzahl bestimmter Werte aus der durch Kommas getrennten Liste erhält
  • wie man Datensätze aus dieser durch Kommas getrennten Liste erhält, die nur denselben 2/3/etc-spezifischen Wert haben

Ein weiteres Problem mit der durch Kommas getrennten Liste besteht darin, sicherzustellen, dass die Werte konsistent sind - das Speichern von Text bedeutet die Möglichkeit von Tippfehlern ...

Dies sind alles Symptome von denormalisierten Daten und zeigen, warum Sie immer für normalisierte Daten modellieren sollten. Denormalisierung kann eine Abfrageoptimierung sein, angewendet werden, wenn sich der Bedarf tatsächlich ergibt .

39
OMG Ponies

Im Allgemeinen kann alles verteidigt werden, wenn es den Anforderungen Ihres Projekts entspricht. Das bedeutet nicht, dass die Leute Ihrer Entscheidung zustimmen oder sie verteidigen wollen ...

Im Allgemeinen ist das Speichern von Daten auf diese Weise nicht optimal (z. B. schwieriger, effiziente Abfragen durchzuführen) und kann zu Wartungsproblemen führen, wenn Sie die Elemente in Ihrem Formular ändern. Vielleicht hätten Sie einen Mittelweg finden und stattdessen eine Ganzzahl verwenden können, die eine Reihe von Bit-Flags darstellt?

18
bobbymcr

Ja, ich würde sagen, dass es wirklich so schlimm ist. Es ist eine vertretbare Wahl, aber das macht es nicht richtig oder gut.

Es bricht die erste Normalform.

Ein zweiter Kritikpunkt ist, dass das direkte Einfügen von Roheingabe-Ergebnissen in eine Datenbank ohne jegliche Validierung oder Bindung Sie für SQL-Injection-Angriffe offen lässt.

Was Sie als Faulheit und Mangel an SQL-Kenntnissen bezeichnen, ist das Material, aus dem Neophyten bestehen. Ich würde empfehlen, sich die Zeit zu nehmen, um es richtig zu machen und es als Gelegenheit zum Lernen zu betrachten.

Oder lassen Sie es wie es ist und lernen Sie die schmerzhafte Lektion eines SQL-Injection-Angriffs.

12
duffymo

Ich brauchte eine mehrwertige Spalte, die als XML-Feld implementiert werden konnte

Es kann nach Bedarf in ein Komma umgewandelt werden

Abfragen einer XML-Liste in SQL Server mit Xquery .

Als XML-Feld können einige der Probleme behoben werden.

Mit CSV: Es kann nicht sichergestellt werden, dass jeder Wert den richtigen Datentyp aufweist: Keine Möglichkeit, 1,2,3, Banane, 5 zu verhindern

Mit XML: Werte in einem Tag können gezwungen werden, den richtigen Typ zu haben


Mit CSV: Fremdschlüsseleinschränkungen können nicht zum Verknüpfen von Werten mit einer Nachschlagetabelle verwendet werden. Keine Möglichkeit, die referenzielle Integrität durchzusetzen.

Mit XML: immer noch ein Problem


Mit CSV: Eindeutigkeit nicht erzwingen: Keine Möglichkeit, 1,2,3,3,3,5 zu verhindern

Mit XML: immer noch ein Problem


Mit CSV: Ein Wert kann nicht aus der Liste gelöscht werden, ohne die gesamte Liste abzurufen.

Mit XML: können einzelne Elemente entfernt werden


Mit CSV: Es ist schwierig, nach allen Entitäten mit einem bestimmten Wert in der Liste zu suchen. Sie müssen einen ineffizienten Tabellenscan verwenden.

Mit XML: XML-Feld kann indiziert werden


Mit CSV: Schwer zu zählende Elemente in der Liste oder andere aggregierte Abfragen. **

Mit XML: nicht besonders schwer


Mit CSV: Es ist schwierig, die Werte mit der Nachschlagetabelle zu verknüpfen, auf die sie verweisen. **

Mit XML: nicht besonders schwer


Mit CSV: Es ist schwierig, die Liste in sortierter Reihenfolge abzurufen.

Mit XML: nicht besonders schwer


Mit CSV: Das Speichern von Ganzzahlen als Zeichenfolgen nimmt etwa doppelt so viel Platz ein wie das Speichern von binären Ganzzahlen.

Mit XML: Speicher ist noch schlimmer als eine CSV


Mit CSV: Plus viele Kommazeichen.

Bei XML: Tags werden anstelle von Kommas verwendet


Kurz gesagt, die Verwendung von XML umgeht einige Probleme mit der Liste mit Trennzeichen UND kann bei Bedarf in eine Liste mit Trennzeichen konvertiert werden

7
James A Mohler

Nun, ich verwende seit mehr als 4 Jahren eine tabulatorgetrennte Liste mit Schlüssel-/Wertepaaren in einer NTEXT-Spalte in SQL Server und das funktioniert. Sie verlieren zwar die Flexibilität beim Erstellen von Abfragen, aber wenn Sie andererseits eine Bibliothek haben, die das Schlüsselwertpaar beibehält/derpergiert, ist dies keine so schlechte Idee.

7
Raj

Ja, es ist ist so schlimm. Meiner Ansicht nach gibt es viele interessante "NOSQL" -Projekte mit einigen wirklich fortgeschrittenen Funktionen, wenn Sie nicht gerne relationale Datenbanken verwenden, und wenn Sie eine Alternative suchen, die besser zu Ihnen passt.

6
Robin

Ich würde wahrscheinlich den Mittelweg nehmen: jedes Feld in der CSV in eine separate Spalte in der Datenbank machen, aber nicht viel über die Normalisierung (zumindest für den Moment) sorgen. Irgendwann wird die Normalisierung könnte interessant, aber wenn alle Daten in eine einzige Spalte verschoben werden, hat die Verwendung einer Datenbank praktisch keinen Nutzen mehr. Sie müssen die Daten in logische Felder/Spalten/wie auch immer Sie sie aufrufen möchten, trennen, bevor Sie sie überhaupt sinnvoll bearbeiten können.

0
Jerry Coffin

Wenn Sie eine feste Anzahl von Booleschen Feldern haben, können Sie für jedes ein INT(1) NOT NULL (oder BIT NOT NULL, Falls vorhanden) oder CHAR (0) (nullable) verwenden. Sie können auch ein SET verwenden (ich vergesse die genaue Syntax).

0
Solomon Ucko