Alternative zu EAV für dynamische Felder in einem Star-Schema-Data-Warehouse

13

Ich muss dynamische Felder und Werte in einem großen Datawarehouse für das Speichern des API-Anforderungsprotokolls unterstützen. Mein Anwendungsfall ist, dass ich alle API-Anforderungs-Abfragezeichenfolgen speichern und in der Lage sein muss, in Zukunft eine Abfrage für sie durchzuführen (es handelt sich also nicht nur um die Speicherung. Also kann ich keinen Blob für sie verwenden.)

z.B http://example.com/?action=test&foo=abc&bar=def...

Ich muss alle field => valueZuordnungen speichern , dh (action => test), (foo => abc), (bar => def), da das Feld so dynamisch ist, habe ich nur die Lösung gefunden, Entity-Attribute-Value zu verwenden. Es wird jedoch immer wieder behauptet, dass es sich um ein sehr schlechtes Design handelt.

Betrachten Sie also meinen obigen Anwendungsfall, was wäre eine geeignete Alternative zu EAV?

Mein aktuelles Schema mit KAV

  1. Tisch requests
    (id, timestamp, uri)
    zB(1, 149382220, '/')

  2. Tisch params
    (request_id, key, value)
    zB(1, 'action', 'test'), (1, 'foo', 'abc'), (1, 'bar', 'def')

Irgendwelche Vorschläge?

Update: Wir führen das Warehouse auf AWS RedShift aus

Howard
quelle
2
Was ist falsch daran, zu versuchen, was Sie in einer Entwicklerdatenbank vorschlagen? Sprechen Sie auch über SQL Server? Das SQL- Tag ist ziemlich breit.
Max Vernon
Meine Frage wurde aktualisiert
Howard
1
Welches DBMS verwenden Sie? Einige haben ziemlich gute Indizierungsfunktionen für Text, sodass ich nicht ausschließen würde, ein "Langtext" -Feld zum Speichern von Anforderungen zu verwenden. Abgesehen davon hätte ich kein Problem damit, das von Ihnen vorgeschlagene Modell zu verwenden. EAV wird streng genommen nur für diesen speziellen Zweck verwendet. Welche Art von Fragen müssen Sie jedoch erneut stellen, um in der Lage zu sein, dies zu tun? Versuchen Sie, diese Abfragen für dieses Modell zu schreiben, um festzustellen, ob sie für Sie funktionieren.
Colin 't Hart
1
Welches RDBMS verwenden Sie? SQList nicht spezifisch genug. Du wurdest zweimal gefragt. Ich bin der dritte
Erwin Brandstetter
2
Da RedShift auf PostgreSQL basiert, würde ich versuchen , das verwenden hstoreoder jsonDatentypen (oder jsonbob / wann sie „Upgrade“ auf 9,4).
Colin 't Hart

Antworten:

11

Ich kann mir drei Lösungen vorstellen - EAV, XML und Sparse Columns. Letzteres ist herstellerspezifisch und für Sie möglicherweise nicht hilfreich.

Unabhängig von der gewählten Methode können Sie die ursprünglichen Anforderungsdaten in einem unformatierten Format, in einer Tabelle oder in einer Einfachdatei speichern. Sie können auf einfache Weise neue Möglichkeiten zum Speichern der Daten ausprobieren, Daten neu laden, wenn Sie einen Fehler beim Parsen Ihrer Anforderungen feststellen, und die API-Anforderungen mithilfe von Stapelverarbeitung oder "Big Data" analysieren. Tools, wenn Sie feststellen, dass Ihr Data Warehouse die Daten nicht effizient verarbeiten kann.

Überlegungen zur EAV

EAV / KVS, wie Sie es oben beschrieben haben, ist wahrscheinlich die einfachste Implementierung.

Leider wird es auch sehr teuer - um effiziente Abfragen zu häufig verwendeten Schlüsseln zu erhalten, benötigen Sie Indizes in der Schlüsselspalte, die sehr fragmentiert werden können. Das Abfragen bestimmter Schlüssel wäre extrem teuer.

Möglicherweise können Sie die Kosten für die Indizierung oder Indexsuche senken, indem Sie Ihren EAV-Speicher mit materialisierten Ansichten (viele Anbieter unterstützen dies) zum Abfragen von Schlüsseln oder Werten unterstützen, die Sie interessieren.

XML

Die meisten Unternehmensdatenbanksysteme bieten eine sehr ausgereifte XML-Verarbeitung, einschließlich Validierung, Indizierung und komplexer Abfragen.

Wenn Sie die API-Anforderung als XML in die Datenbank laden, erhalten Sie ein Tupel pro Anforderung. Dies ist logischerweise für Sie möglicherweise etwas angenehmer als eine unbekannte Anzahl von Zeilen in einer EAV-Tabelle.

Ob dies effizient ist, hängt stark von Ihrem RDBMS-Anbieter und Ihrer Implementierung ab.

Der größte Nachteil ist, dass dies wahrscheinlich die einzige Möglichkeit ist, Daten zu verwalten, die komplizierter ist als die Manipulation von Zeichenfolgen der ursprünglichen Anforderung!

Sparse Columns / traditionelle Tische

Es ist möglich, dass Sie Ihre Daten in eine herkömmliche Tabellenstruktur mit einer Spalte pro Schlüssel laden.

Die Funktion " Sparse Columns" von SQL Server ist eine hervorragende Alternative zu einem EAV-Speicher. Eine Tabelle mit Spalten mit geringer Dichte verhält sich ähnlich wie eine normale Tabelle, außer dass sie bis zu 30.000 Spalten enthalten kann und NULL-Werte in Spalten mit geringer Dichte keinen Speicherplatz in der Tabelle belegen.

Die Kombination mit gefilterten Indizes (eine weitere SQL Server-spezifische Funktion) kann eine äußerst effiziente Alternative zu einem EAV-Speicher darstellen, wenn Sie häufig nach bestimmten Spalten und / oder Werten fragen.

Die Verwendung einer herkömmlichen Tabelle mit anderen Anbietern kann sinnvoll sein - IBM unterstützt über 700 Spalten pro Tabelle und Oracle etwa 1000. Funktionen wie die Komprimierung oder die Behandlung von nachgestellten Nullen durch Oracle können dazu führen, dass Sie Ihre API-Daten relativ effizient speichern können.

Der offensichtliche Nachteil dieses Ansatzes ist, dass Sie beim Hinzufügen neuer Schlüssel zu Ihrer API Ihr Schema entsprechend anpassen müssen.

Nathan Jolly
quelle
2
In PostgreSQL würde ich XML aber entweder hstoreoder nicht empfehlen json. Im kommenden 9.4 jsonbwäre meine Empfehlung.
Colin 't Hart
Ich mag diese Antwort mit den Vor- und Nachteilen und Erklärungen von jedem. Sehr informativ - ich schätze auf jeden Fall die Sparse Columns Info. Ich möchte ein Beispiel für EAV mit dem Ansatz der spärlichen Spalten.
StixO
9

EAV ist an sich kein schlechtes Design, es ist einfach ein Design, das eine angemessene Menge an Voraussicht erfordert und mit Leistungsproblemen bewerkstelligt werden kann, wenn die Datenmenge steigt. Es kann sein, dass es für Ihr System gut funktionieren würde.

Als ich ein System zum Speichern von Abfragezeichenfolgen entwarf, hatte ich keine Ahnung , welche Felder mich interessieren würden. Ich erstellte eine Tabelle zum Speichern der Abfragezeichenfolge im serialisierten Binärformat und erstellte ein System, mit dem ich die Abfrage aufteilen konnte Zerlegen Sie die Teile in Einzelteile, sobald ich die Teile kannte, an denen ich interessiert war. Von dort aus erstellte ich eine Reihe von Tabellen. jeweils eine für die Datensätze, die üblicherweise in der Abfragezeichenfolge enthalten sind.

Zum Beispiel hatte ich irgendwann eine Tabelle für Verweisdaten, eine für Zielanforderungsdaten und eine für benutzerbezogene Elemente wie die von ihnen eingegebene Suchabfrage.

Ich fand die Möglichkeit, die gesamte Abfragezeichenfolge in einer einzelnen Tabelle als Blob zu speichern, und die Möglichkeit, diesen Blob in Zukunft aufzuteilen, erfüllte meine Anforderungen sehr gut.

Max Vernon
quelle
1
Sowohl in der Frage als auch in der Antwort wird der Begriff BLOBverwendet, der Binary Long OBject bedeutet. Ich würde es vorziehen, ein CLOB(Character Long OBject) oder ähnliches textin PostgreSQL zu verwenden, da es sich um Zeichen und nicht um Binärdaten handelt.
Colin 't Hart
2
Ich habe ein binäres Feld verwendet, da ich das gesamte Sitzungsobjekt serialisiert und das gesamte Objekt in der Datenbank gespeichert habe.
Max Vernon