2017-03-16 15 views
0

Ich habe dieses Design.Datenbankentwurf für mehrere Modelle?

Tabelle models:

id - primary key 
title - varchar(256) 

Tabelle model_instances:

id - primary key 
model_id - foreign key to app_models.id 
title - varchar(256) 

Tabelle model_fields:

id - pk 
model_id - foreign key to models.id 
instance_id - foreign key to model_instances.id 
title - name of the field 
type - enum [text, checkbox, radio, select, 'etc'] 

Tabelle model_field_values:

instance_id - forein key model_instance.id 
field_id - foreign key to model_fields.id 
value - text 

Auch kann es viele values für einige Feld (für Mehrfachauswahl Dropdown wie) sein

Das Problem ist: value immer text Feld ist, weil ich integer verschiedene Arten von Daten (Text, Datetime, speichern möchten) und diese Tabelle enthält alle Werte für alle Instanzen aller Modelle.

Zum Beispiel, wenn ich 10 Modelle habe und jedes Modell 1000 Instanzen mit 10 Feldern hat, dann würde model_field_values ​​(mindestens) 100000 Zeilen enthalten, wenn einige Felder mehrere sind, dann würde es (120000-150000 Zeilen) enthalten.

SQL-Auswahl mit value Feld wäre langsam.

Lösung 1:

For every model create new model_field_values like: 

model.id = 1, model_field_values_1 
... 
model.id = 10, model_field_values_10 

Lösung 2:

Da model_fields alle Felder für das Modell enthält, können wir model_field_values ​​ähnliche

model_fields für model.id = 1 (Primärschlüssel erstellen): 1 - text, 2 - integer, 3 - datetime, 4 - kleintext

Felder für model_field_values_1: field_1 text, field_2 integer, field_3 datetime, fie ld_4 varchar (256)

Diese Lösung eignet sich nicht für Felder mit mehreren Werten, da jeder multiple Wert eine andere Tabelle mit einer Verknüpfung zur Zeile in model_field_values_1 haben sollte, aber gut für die Datenbanksuche, da mysql native Datentypen verwendet in Where-Klauseln (keine Textfelder).

Kann ich etwas verpassen? Kann es sein, dass es ein besseres Design gibt?

Diese Datenbank würde im crm-System verwendet werden, wo der Benutzer ein anderes Modell mit vielen Instanzen in diesen Modellen erstellen kann, so dass ich nicht alle Tabellen mit allen Spalten vorkonfigurieren kann.

Antwort

0

Hinweis: 200.000 Zeilen (zwei Zehntel eines Megarows) ist im normalen Betrieb von MySQL eine mittelgroße Tabelle. Es ist im Allgemeinen möglich, eine solche Tabelle ziemlich effizient zu indizieren. http://use-the-index-luke.com/

aber sagen, dass Ich denke ich Ihr Problem verstehen. Es ist im Jargon des objektorientierten Designs Polymorphismus.

Sie haben diese model_field_value Tabelle ist

instance_id 
field_id 
value 

Ihr Problem enthalten, der native Datentyp des Wertes ist manchmal VARCHAR(255), manchmal DATETIME oder vielleicht TIMESTAMP, und manchmal INT.

Und Sie werden manchmal Anfragen wie diese

SELECT fv.instance_id 
    FROM model_field_value fv 
    WHERE fv.field_id = something 
    AND fv.value >= '2017-01-01' 
    AND fv.value < '2018-01-01' 

finden DATETIME Werte tun müssen, das Jahr in Kalender geschah 2017. Zum Beispiel.

Dies ist in der Regel ein Schmerz im Nacken mit Schlüssel/Wert-Speicher wie, was Sie brauchen. Für eine Abfrage wie mein Beispiel zu sargable, müssen Sie in der Lage sein, einen Index auf eine Spalte zu setzen. Aber wenn Sie keine solche Spalte haben, können Sie sie nicht indizieren. Duh.

Hier ist ein Vorschlag. Gib deinem Tisch diese Spalten.

instance_id  INT pk fk 
field_id   INT pk fk 
value   VARCHAR(255) a text representation of every value. 
value_double  DOUBLE  a numeric representation of every numeric value, or NULL 
value_ts   TIMESTAMP  a timestamp value if possible, or NULL 

Diese Tabelle wird redundante Daten enthalten, und Sie werden sehr vorsichtig sein, wenn Sie es gerade schreiben, um sicherzustellen, dass es richtig ist. Aber Sie können Indizes auf die Spalten value_ts und value_double setzen, sodass Sie diese Art von Abfragen als Sargable definieren können.

Nur eine Idee.