Ich würde einige Meinungen über eine Sorge schätzen, die ich habe.
Ich habe eine [User] -Tabelle in meiner Datenbank, mit den grundlegenden Dingen, die Sie erwarten, wie Benutzername, Passwort, etc ...
Diese Anwendung erfordert, dass ich eine große Anzahl von Attributen für jeden Benutzer verfolgen. So sehr, dass ich wahrscheinlich keine Spalten mehr habe (Zeilenspeicherplatz).
Ich bin versucht, eine UserProperties-Tabelle mit den Spalten UserID, PropertyKey und PropertyValue hinzuzufügen. Dieser Ansatz passt gut zu den Anforderungen.
Meine Sorge ist, dass, wenn jeder Benutzer 100 Eigenschaften sagt, wenn die Datenbank eine Million Benutzer darin hat, wir 100.000.000 Eigenschaftenzeilen haben werden.
Ich würde denken, dass mit einem Clustered-Index auf der UserID dieser Zugriff immer noch schnell geschrieen wird und Sie ungefähr die gleiche Menge an Daten speichern, wie Sie es mit dem Megasäulen-Ansatz tun würden.
Irgendwelche Ideen oder Gedanken zu Performance-Bedenken? Ideen für ein besseres DB-Design?
Danke!
UPDATE:
Erstens, vielen Dank für all die tollen Antworten!
Ich habe mit den Möglichkeiten herumgespielt und eine Sache beschäftigt mich immer wieder. Ich muss einige dieser Attribute ziemlich häufig abfragen, und noch schlimmer, diese Abfragen können beinhalten, alle Benutzer zu finden, die Kriterien für bis zu 10 dieser Attribute gleichzeitig erfüllen.
Als Ergebnis lehne ich mich jetzt dem Mega-Column-Ansatz zu, aber möglicherweise splitten Sie die Daten in eine (oder mehrere) separate Tabellen auf und bilden eine Eins-zu-Eins-Beziehung, die über die UserID eingegeben wird.
Ich benutze LinqToSql, und obwohl ich denke, dass Tabellen mit so vielen Spalten unelegant sind, denke ich, wenn man alle Herausforderungen und Kompromisse betrachtet, ist es wahrscheinlich die richtige, aber ich bin immer noch gespannt auf andere Meinungen.
Was Sie beschreiben, ist eine Entity-Attribut-Value-Datenbank, die oft für genau die Situation verwendet wird, die Sie beschreiben, spärliche Daten, die an eine einzelne Entität gebunden sind.
Eine E-A-V-Tabelle ist einfach zu suchen. Das Problem besteht darin, keine Zeilen zu finden, sondern verwandte Zeilen.
Verschiedene Tabellen für verschiedene Entitäten bieten Domänenmodellierung, aber sie bieten auch eine schwache Form von Metadaten. In E-A-V gibt es solche Abstraktionen nicht. (Die Java-Analogie zu E-A-V würde erklären, dass die formalen Argumente aller Funktionen vom Typ Object sind - also würden Sie keine Typüberprüfung erhalten.)
Wir können die Eigenschaftsschlüssel leicht nachschlagen, aber nichts gruppiert diese Eigenschaftsschlüssel.
Wikipedia hat einen sehr guten Artikel über E-A-V, aber lies es jetzt - es ist hauptsächlich die Arbeit eines Autors und ist für "Verbesserung" vorgesehen.
Ich empfehle Ihnen, den Ansatz der vertikalen Partitionierung zu verwenden. Das bedeutet, dass Sie Tabellen mit einem Benutzer-ID-Schlüssel definieren, Sie könnten sie als Benutzer1, Benutzer2 usw. bezeichnen. Starten Sie eine neue Tabelle, wenn Sie die maximale Zeilengröße für Ihre Datenbank erreicht haben. Der Vorteil dieses Ansatzes besteht darin, dass die Werte immer noch echte Datenbankattribute sind. Dies spart Zeit beim Arbeiten mit diesen Daten, z. Datenbindung.
Die Schlüsselfrage lautet: Sind das wirklich Attribute? Stellen sie die Struktur von Informationen dar, die Sie über den Benutzer sammeln müssen. Wenn dies der Fall ist, besteht die beste Möglichkeit, sie zu modellieren, darin, sie zu Spalten zu machen. Der einzige Grund, warum Sie auf die vertikale Partitionierung zurückgreifen müssen, ist die Zeilengrößenbeschränkung der Datenbank.
Wenn andererseits ein flexibles Attributsystem aufgerufen wird, dann gehen Sie auf jeden Fall mit dem Eigenschaftsschlüssel / Eigenschaftswertsystem. Wenn Benutzer z. B. ihre eigenen Attribute dynamisch definieren dürfen, möchten Sie das Schlüssel / Wert-System. Ich würde jedoch sagen, Schlüssel / Wert ist nicht der beste Weg, wenn Sie die Struktur Ihrer Daten verstehen und rechtmäßig Hunderte von Attributen für Benutzer identifiziert haben.
Als Nebenbemerkung muss ich sagen, dass Sie Entitäten mit einer großen Anzahl von Attributen hinterfragen sollten. Sie sind möglicherweise gültig, aber es ist auch sehr wahrscheinlich, dass Sie einige Entitäten auf konzeptioneller Ebene vermissen. Mit anderen Worten, alle diese Attribute beziehen sich nicht auf den Benutzer selbst, sondern auf eine andere Entität, die sich auf Benutzer bezieht.
Der Ansatz der UserProperties-Tabelle ist, wie ich es modellieren würde. Wie Sie vorgeschlagen haben, bedeutet ein Clustered-Index für Benutzer-ID, dass die Bereichssuche auf der Benutzer-ID schnell erfolgt (d. H. Für alle Eigenschaften, die sich auf einen einzelnen Benutzer beziehen). Fügt möglicherweise auch einen nicht gruppierten Index für UserID und PropertyKey für einzelne Schlüssel-2-Wert-Auswahl pro Benutzer hinzu.
Ich bezweifle, dass Sie so viele 1-zu-1-Datenwerte in der Tabelle "Benutzer" haben, in denen Sie keinen Zeilenspeicher mehr haben. Sie sollten nur 1-zu-Viele-Werte in eine andere Tabelle verschieben, indem Sie die Benutzer-ID als Fremdschlüssel verwenden. Ich finde es unwahrscheinlich, dass Ihre Benutzertabelle so viele VARCHAR () - Felder benötigt, die irgendwie nicht aus einer Haupttabelle von Werten in FKs umgewandelt werden können. Welche Art von Benutzerattributen pflegen Sie?
Gibt es eine Möglichkeit, die Eigenschaften logisch zu gruppieren? Sie müssen nicht immer auf alle Objekte zugreifen. Wenn sie logisch gruppiert sind, wird es einfacher, einen Sinn zu finden, welche Eigenschaften verfügbar sind, wo neue Eigenschaften passen usw. ...
Die Gruppierungen können eine eins zu eins oder eine zu viele Beziehung mit dem Benutzer haben ...
Wir haben die UserProperties-Strategie in mehreren Projekten implementiert. Dies ist ein gängiges Muster und bei entsprechenden Indizes haben wir noch nie ein Leistungsproblem festgestellt.
Ein weiterer Vorteil ist, dass Sie zwei oder mehr Eigenschaftstabellen haben können, wenn Sie den Benutzerzugriff verwalten müssen. Zum Beispiel könnten allgemeine Eigenschaften in der Tabelle PublicUserProps enthalten sein, während vertrauliche Informationen (ich weiß nicht, was Sie speichern, aber ssn's, Gehaltsabrechnungsinformationen usw.) in einer ControlledUserProps-Tabelle sein könnten, die nur einige Benutzer gelesen oder bearbeitet hätten Rechte.
Ich mag den Metatable-Ansatz, den Mitch Wheat und Sie selbst beschrieben haben. Wenn Sie jedoch einige Felder verwenden, die häufiger verwendet werden als andere (z. B. Name usw.), können Sie feststellen, dass diese Felder in der Benutzertabelle nützlich sein können, und verknüpfen Sie dann die Benutzertabelle mit den UserProperties. Ich schätze, alles hängt von den genauen Details deines Designs ab.
Einige Optionen, die ich mir vorstellen kann:
Angesichts der angegebenen Einschränkungen glaube ich nicht, dass Sie wirklich eine andere Wahl haben!
ok, Sie könnten die Benutzerattribute auf mehrere Tabellen aufteilen, die dieselbe UserId wie ihr Primärschlüssel (und Clustered-Index) teilen, dies verbessert jedoch möglicherweise die Leistung
Wenn Sie nur über 100 Attribute sprechen, könnte dies von einer Tabelle gehandhabt werden (in MS-SQL ist max 1023 Nicht-Schlüsselspalten); Wenn die Attribute nur spärlich belegt sind, kann eine Benutzerattributtabelle möglicherweise platzsparender sein (nur Ihr Profiler weiß es genau)
Ich würde denken, dass mit einem Clustered-Index auf der UserID dieser Zugriff immer noch schnell geschrieen wird und Sie tatsächlich ungefähr die gleiche Datenmenge speichern, wie Sie es mit dem Mega-Columns-Ansatz tun würden.
Ich denke, dass Sie mit einer Eigenschaftentabelle viel mehr speichern werden, als Sie tatsächlich benötigen. Nämlich der Extra-Index der Benutzer-ID, die Property-Key-Spalte und die Tatsache, dass der Eigenschaftswert in der Lage sein muss, generische Werte zu handhaben, die eine Optimierung erschweren.
Ich rate dazu, alles in eine Tabelle zu schreiben und dann mit einigen Testdaten zu starten. WENN es nicht funktioniert, dann könntest du den Weg einer Lösung mit mehreren Tabellen oder sogar einer Nicht-DB-Lösung gehen (sie sind ja keine Silberkugeln).
Tags und Links database-design