Ich habe versucht, eine Datenbank zu entwerfen, die zu einem Projektkonzept passt, und bin auf ein Problem gestoßen, das anscheinend heiß diskutiert wurde. Ich habe ein paar Artikel gelesen und einige Stack Overflow-Antworten, die besagen, dass es nie (oder fast nie) in Ordnung ist, eine Liste von IDs oder Ähnlichem in einem Feld zu speichern - alle Daten sollten relational sein usw.
Das Problem, auf das ich stoße, ist, dass ich versuche, einen Aufgabenzuweiser zu erstellen. Die Benutzer erstellen Aufgaben, weisen sie mehreren Benutzern zu und speichern sie in der Datenbank.
Wenn ich diese Aufgaben einzeln in "Person" speichere, muss ich natürlich Dutzende von Dummy-Spalten "TaskID" haben und sie mikroverwalten, da beispielsweise einer Person 0 bis 100 Aufgaben zugewiesen werden können.
Andererseits, wenn ich die Aufgaben in einer "Aufgaben" -Tabelle speichere, muss ich Dutzende von Dummy "PersonID" -Spalten haben und sie mikro-verwalten - das gleiche Problem wie zuvor.
Ist es für ein Problem wie dieses in Ordnung, eine Liste von IDs in der einen oder anderen Form zu speichern, oder denke ich nur nicht an einen anderen Weg, wie dies erreicht werden kann, ohne die Prinzipien zu brechen?
quelle
VARCHAR ARRAY
), um eine Liste von Tags zu speichern. Das ist wahrscheinlich nicht der Grund, warum sie später gespeichert werden, aber Listen können während der Prototyping-Phase äußerst nützlich sein, wenn Sie auf nichts anderes verweisen müssen und nicht das gesamte Datenbankschema aufbauen möchten, bevor Sie können mach irgendetwas anderes.Antworten:
Das Schlüsselwort und Schlüsselkonzept Sie untersuchen müssen , ist Datenbank Normalisierung .
Anstatt Informationen zu den Zuweisungen zu den Personen- oder Aufgabentabellen hinzuzufügen, fügen Sie eine neue Tabelle mit diesen Zuweisungsinformationen und relevanten Beziehungen hinzu.
Zum Beispiel haben Sie folgende Tabellen:
Personen:
Aufgaben:
Sie würden dann eine dritte Tabelle mit Zuweisungen erstellen. Diese Tabelle würde die Beziehung zwischen den Personen und den Aufgaben modellieren:
Wir hätten dann eine Fremdschlüssel-Einschränkung, sodass die Datenbank erzwingt, dass die Personen-ID und die Aufgaben-ID gültige IDs für diese Fremdelemente sein müssen. Für die erste Reihe, können wir sehen
PersonId is 1
, so Alfred , zugeordnet istTaskId 3
, Kühe melken .Was Sie hier sehen sollten, ist, dass Sie so wenige oder so viele Aufgaben pro Aufgabe oder pro Person haben können, wie Sie möchten. In diesem Beispiel ist Hesekiel keine Aufgabe zugewiesen, und Alfred ist 2 zugewiesen. Wenn Sie eine Aufgabe mit 100 Personen ausführen,
SELECT PersonId from Assignments WHERE TaskId=<whatever>;
werden 100 Zeilen mit einer Vielzahl von verschiedenen Personen zugewiesen. InWHERE
der PersonId können Sie alle dieser Person zugewiesenen Aufgaben suchen.Wenn Sie Abfragen zurückgeben möchten, indem Sie die IDs durch die Namen und die Tasks ersetzen, lernen Sie, wie Sie Tabellen verbinden.
quelle
Sie stellen hier zwei Fragen.
Zuerst fragen Sie, ob es in Ordnung ist, Listen zu speichern, die in einer Spalte serialisiert sind. Ja es ist gut. Wenn Ihr Projekt es erfordert. Ein Beispiel könnten Produktbestandteile für eine Katalogseite sein, bei der Sie nicht versuchen möchten, jeden Bestandteil einzeln zu verfolgen.
Leider beschreibt Ihre zweite Frage ein Szenario, in dem Sie sich für einen relationaleren Ansatz entscheiden sollten. Du brauchst 3 Tische. Eine für die Personen, eine für die Aufgaben und eine, die die Liste der Aufgaben verwaltet, die welchen Personen zugewiesen sind. Das letzte wäre vertikal, eine Zeile pro Person / Aufgabenkombination, mit Spalten für Ihren Primärschlüssel, Ihre Aufgaben-ID und Ihre Personen-ID.
quelle
Was Sie beschreiben, ist in Ihrem Fall als "viele zu viele" Beziehung zwischen
Person
und bekanntTask
. Es wird normalerweise mithilfe einer dritten Tabelle implementiert, die manchmal als "Link" - oder "Querverweistabelle" bezeichnet wird. Zum Beispiel:quelle
task_id
zuerst einen Index hinzufügen , wenn Sie Abfragen ausführen, die nach Aufgaben gefiltert sind.Das einzig Mal , Sie könnten mehr als ein Datenelement in einem einzigen Feld speichern, wenn das Feld ist nur immer als eine Einheit verwendet und wird nie als aus diesen kleineren Elementen berücksichtigt. Ein Beispiel könnte ein Bild sein, das in einem BLOB-Feld gespeichert ist. Es besteht aus vielen, vielen kleineren Elementen (Bytes), die jedoch für die Datenbank nichts bedeuten und nur zusammen verwendet werden können (und für einen Endbenutzer hübsch aussehen).
Da eine "Liste" per Definition aus kleineren Elementen (Elementen) besteht, ist dies hier nicht der Fall und Sie sollten die Daten normalisieren.
Nein. In einer Kreuzungstabelle (auch bekannt als schwache Entität) befinden sich einige Zeilen zwischen Person und Aufgabe. Datenbanken können sehr gut mit vielen Zeilen arbeiten. Sie sind eigentlich ziemlich albern, wenn sie mit vielen [wiederholten] Spalten arbeiten.
Nettes klares Beispiel von Whatsisname.
quelle
In bestimmten vorberechneten Bereichen kann dies legitim sein.
Wenn einige Ihrer Abfragen teuer sind und Sie vorberechnete Felder verwenden, die mithilfe von Datenbank-Triggern automatisch aktualisiert werden, ist es möglicherweise legitim, die Listen in einer Spalte zu belassen.
In der Benutzeroberfläche möchten Sie diese Liste beispielsweise in einer Rasteransicht anzeigen, in der jede Zeile nach einem Doppelklick vollständige Details (mit vollständigen Listen) öffnen kann:
Sie aktualisieren die zweite Spalte nach Auslöser, wenn der Kunde einen neuen Artikel oder eine geplante Aufgabe besucht.
Sie können ein solches Feld auch für die Suche zur Verfügung stellen (als normaler Text).
In solchen Fällen ist das Führen von Listen legitim. Sie müssen nur den Fall berücksichtigen, dass möglicherweise die maximale Feldlänge überschritten wird.
Wenn Sie Microsoft Access verwenden, sind die angebotenen mehrwertigen Felder ein weiterer spezieller Anwendungsfall. Sie bearbeiten Ihre Listen in einem Feld automatisch.
Sie können jedoch jederzeit auf die in anderen Antworten angegebene normalisierte Standardform zurückgreifen.
Zusammenfassung: Normale Datenbankformen sind theoretische Modelle, die zum Verständnis wichtiger Aspekte der Datenmodellierung erforderlich sind . Bei der Normalisierung werden jedoch natürlich weder die Leistung noch andere Kosten für das Abrufen der Daten berücksichtigt. Es liegt außerhalb des Geltungsbereichs dieses theoretischen Modells. Das Speichern von Listen oder anderen vorberechneten (und kontrollierten) Duplikaten ist jedoch häufig durch die praktische Implementierung erforderlich.
Würden wir im Lichte der obigen Ausführungen in der praktischen Umsetzung eine Abfrage bevorzugen, die sich auf die perfekte Normalform stützt und 20 Sekunden lang ausgeführt wird, oder eine äquivalente Abfrage, die sich auf vorberechnete Werte stützt, die 0,08 s dauern? Niemand mag es, wenn sein Softwareprodukt der Langsamkeit beschuldigt wird.
quelle
Zwei Tische gegeben; Wir nennen sie Person und Task, jede mit ihrer eigenen ID (PersonID, TaskID). Die Grundidee ist, eine dritte Tabelle zu erstellen, um sie miteinander zu verbinden. Wir nennen diese Tabelle PersonToTask. Zumindest sollte es eine eigene ID haben, ebenso wie die beiden anderen. Also, wenn es darum geht, jemanden einer Aufgabe zuzuweisen; Sie müssen die Person-Tabelle nicht mehr aktualisieren, sondern müssen lediglich eine neue Zeile in die PersonToTaskTable einfügen. Und die Wartung wird einfacher - das Löschen einer Aufgabe wird einfach zu einem LÖSCHEN basierend auf der Aufgaben-ID, wodurch die Personentabelle und das damit verbundene Parsen nicht mehr aktualisiert werden
Wie wäre es mit einem einfachen Bericht oder wer ist einer Aufgabe zugeordnet?
Sie könnten natürlich noch viel mehr tun. Ein TimeReport kann durchgeführt werden, wenn Sie DateTime-Felder für TaskAssigned und TaskCompleted hinzugefügt haben. Es hängt alles von dir ab
quelle
Es kann funktionieren, wenn Sie sagen, dass Sie von Menschen lesbare Primärschlüssel haben und eine Liste von Task-Nrn. Möchten, ohne sich mit der vertikalen Natur einer Tabellenstruktur befassen zu müssen. dh viel einfacher, erste Tabelle zu lesen.
Die Frage wäre dann: Sollte die Aufgabenliste bei Bedarf gespeichert oder generiert werden, was weitgehend von Anforderungen abhängen würde, wie oft die Liste benötigt wird, wie genau wie viele Datenzeilen existieren, wie die Daten verwendet werden usw. .. Danach sollten die Kompromisse zur Benutzererfahrung und zur Erfüllung der Anforderungen analysiert werden.
Vergleichen Sie beispielsweise die Zeit, die zum Abrufen der 2 Zeilen benötigt wird, mit der Ausführung einer Abfrage, die die 2 Zeilen generiert. Wenn es lange dauert und der Benutzer nicht die aktuellste Liste benötigt (* erwartet weniger als 1 Änderung pro Tag), kann es gespeichert werden.
Oder wenn der Benutzer eine historische Aufzeichnung der ihm zugewiesenen Aufgaben benötigt, ist es auch sinnvoll, wenn die Liste gespeichert wurde. Es kommt also wirklich darauf an, was du tust, sag niemals nie.
quelle
Sie nehmen einen anderen Tisch, drehen ihn um 90 Grad und wandeln ihn in einen anderen Tisch um.
Es ist so, als hätten Sie eine Bestelltabelle, in der Sie itemProdcode1, itemQuantity1, itemPrice1 ... itemProdcode37, itemQuantity37, itemPrice37 haben. Abgesehen davon, dass Sie programmgesteuert umständlich sind, können Sie garantieren, dass morgen jemand 38 Dinge bestellen möchte.
Ich würde es nur so machen, wenn die 'Liste' nicht wirklich eine Liste ist, dh wenn sie als Ganzes steht und sich jede einzelne Werbebuchung nicht auf eine klare und unabhängige Entität bezieht. In diesem Fall füllen Sie einfach alles mit einem Datentyp, der groß genug ist.
Eine Bestellung ist also eine Liste, eine Stückliste ist eine Liste (oder eine Liste von Listen, die noch mehr zum Albtraum werden würde, wenn man sie "seitwärts" implementiert). Aber eine Notiz / ein Kommentar und ein Gedicht sind es nicht.
quelle
Wenn es "nicht in Ordnung" ist, ist es ziemlich schlimm, dass jede Wordpress-Site jemals eine Liste in wp_usermeta mit wp_capabilities in einer Zeile, dismissed_wp_pointers in einer Zeile und andere hat ...
In solchen Fällen ist die Geschwindigkeit möglicherweise besser, da Sie die Liste fast immer benötigen . Es ist jedoch nicht bekannt, dass Wordpress das perfekte Beispiel für Best Practices ist.
quelle