2009-02-05 10 views
10

Ich muss eine Schlüssel/Wert-Tabelle in meiner Datenbank entwerfen, und ich suche nach einer Anleitung für den besten Weg, dies zu tun. Grundsätzlich muss ich in der Lage sein, Werte einer dynamischen Gruppe benannter Eigenschaften zuzuordnen und sie auf einen externen Schlüssel anzuwenden.Schlüssel/Wert-Paare in einer Datenbanktabelle

Die Operationen sind Ich muss in der Lage zu unterstützen:

  • ein Schlüssel/Wert-Paar auf eine Gruppe von Elementen
  • Aufzählen alle derzeit aktiven Tasten Nehmen
  • alle das Bestimmen Elemente mit einem Wert für einen bestimmten Schlüssel
  • Ermitteln Sie alle Elemente, bei denen der mit einem bestimmten Schlüssel verknüpfte Wert einigen Kriterien entspricht.

Es scheint, dass der einfachste Weg, dies zu tun ist, um eine Tabelle zu definieren:

CREATE TABLE KeyValue (
    id int, 
    Key varchar..., 
    Value varchar... 
); 

Es scheint, dass ich eine Menge von Daten in der Spalte Schlüssel zu duplizieren sein wahrscheinlich, weil ich Schlüssel jeden gegebenen wird wahrscheinlich für eine große Anzahl von Dokumenten definiert. Das Ersetzen des Schlüssels varchar durch eine Integer-Suche in eine andere Tabelle scheint dieses Problem zu lösen (und macht es wesentlich effizienter, alle aktiven Schlüssel aufzulisten), hält mich jedoch mit dem Problem auf, diese Nachschlagetabelle beizubehalten (wann immer ich will) um eine Eigenschaft zu definieren und möglicherweise den Eintrag bei jedem Löschen eines Schlüssels/Werts zu entfernen.

Was ist der beste Weg, dies zu tun?

Antwort

1

Eine Option, die es wert ist, untersucht zu werden, besteht darin, den Schlüssel mit SHA1 oder MD5 zu verdauen, bevor er in die Tabelle eingefügt wird.

Damit können Sie die Nachschlagetabelle loswerden, aber Sie werden nicht in der Lage sein, durch die Schlüssel zu iterieren, weil es nur in eine Richtung geht.

1

Es scheint mir, als ob Sie ein paar Design-Entscheidungen haben könnten.

Wahl 1: Ein zwei Tabellenentwurf Sie in Ihrer Antwort deuteten

Keys (
id int not null auto_increment 
key string/int 
) 
values (
id int not null auto_increment 
key_id int 
value string/varchar/int 
) 

Wahl 2: vielleicht als sambo99 darauf hingewiesen Sie könnte dies ändern:

keys (
id int not null auto_increment 
key string/int 
hash_code int -- this would be computed by the inserting code, so that lookups would effectively have the id, and you can look them up directly 
) 

values (
id int not null auto_increment -- this column might be nice since your hash_codes might colide, and this will make deletes/updates easier 
key_id int -- this column becomes optional 
hash_code int 
value string/varchar/int... 
) 

-

+0

Chancen von SHA1 kollidieren sind ziemlich 0 in der Realität, müssen Sie super böse sein, um Kollisionen zu verursachen, wenn Sie super besorgt sind, könnten Sie SHA256 verwenden –

+2

Ich habe persönlich eine Hash-Kollision (TTH) in DC++ gesehen, so ist es nicht unmöglich. – erikkallen

5

Optimiere das nicht, es sei denn, du musst es tun. Was ist die durchschnittliche Länge eines Schlüssels? Wird diese Tabelle so groß sein, dass sie nicht in den Speicher Ihres Servers passt, wenn Sie sie naiv implementieren? Ich würde vorschlagen, es auf die einfachste Art und Weise zu implementieren, die Leistung zu messen und es dann nur dann neu zu implementieren, wenn die Leistung ein Problem darstellt.

Wenn Leistung ein Problem ist, dann ist die Verwendung eines Integer-Schlüssels und einer separaten Tabelle wahrscheinlich der Weg zu gehen (JOINS in Integer-Spalten sind in der Regel schneller als JOINS mit Variable-Länge-String-Spalten). Aber die erste Regel der Optimierung ist MEASURE FIRST - stellen Sie sicher, dass Ihr angeblich optimierter Code die Sache schneller macht.

+1

+1 Einfachheit. Wenn die Auswirkungen auf die Leistung nicht offensichtlich und schwerwiegend sind, gehen Sie immer mit dem Programm, mit dem am einfachsten zu arbeiten ist, und testen und optimieren Sie es gegebenenfalls. –

30

Sie verwenden ein Datenbankmodell mit der Bezeichnung Entity-Attribute-Value.Dies ist eine gängige Methode zum Speichern von Schlüssel/Wert-Paaren in einer relationalen Datenbank, weist jedoch eine Reihe von Schwachstellen in Bezug auf die Normalisierung und Effizienz der Datenbank auf.

Ja, das von Ihnen gezeigte Tabellen-Design ist die gebräuchlichste Methode. In diesem Entwurf erhält jedes Attribut jeder Entität eine eigene Zeile in Ihrer Tabelle KeyValue.

Wenden Sie ein Schlüssel/Wert-Paar auf eine Gruppe von Elementen an: Sie müssen für jedes Element in der Gruppe eine Zeile hinzufügen.

INSERT INTO KeyValue (id, key, value) VALUES (101, 'color', 'green'); 
INSERT INTO KeyValue (id, key, value) VALUES (102, 'color', 'green'); 
INSERT INTO KeyValue (id, key, value) VALUES (103, 'color', 'green'); 

Sie können auch die INSERT-Anweisung mit Parametern vorbereitet und durch eine Reihe von Element-IDs in einer Schleife laufen, oder was auch immer.

Aufzählen alle derzeit aktiven Tasten:

SELECT DISTINCT Key FROM KeyValue; 

alle Elemente bestimmen, die einen Wert für einen bestimmten Schlüssel haben:

SELECT id FROM KeyValue WHERE Key = 'color'; 

alle das Bestimmen Elemente, bei denen der mit einem bestimmten Schlüssel verknüpfte Wert bestimmte Kriterien erfüllt:

SELECT id FROM KeyValue WHERE Value = 'green'; 

Einige der Probleme mit Entity-Attribut-Wert sind:

  • Keineswegs sicher Tasten machen die für alle Positionen gleich
  • No way einige Schlüssel obligatorisch für alle Artikel geschrieben sind zu machen (dh NOT NULL in einem herkömmlichen Tischdesign).
  • Alle Schlüssel müssen VARCHAR für den Wert verwenden; Es können keine unterschiedlichen Datentypen pro Schlüssel gespeichert werden.
  • Keine Möglichkeit, referenzielle Integrität zu verwenden; Es kann kein FREMDSCHLÜSSEL erstellt werden, der auf Werte einiger Schlüssel und nicht auf andere Werte angewendet wird.

Grundsätzlich ist Entity-Attribut-Value kein normalisierter Datenbankentwurf.

Verwandte Themen