Datenbankdesign: Neue Tabelle im Vergleich zu neuen Spalten

38

(Dies sollte hier von StackOverflow neu gepostet werden.)

Derzeit haben Sie eine Tabelle .. und müssen neue Datenspalten hinzufügen. Nicht jeder Datensatz (auch wenn nach dem Hinzufügen der neuen Datenspalten neue Daten vorliegen) enthält Daten. Ich frage mich also, ob dies besser für eine neue Tabelle geeignet ist, da es sich tatsächlich um eine Erweiterung einiger Datenzeilen handelt und nicht für jede Zeile gilt.

Mit anderen Worten, da es für diese neuen Datenelemente viele nicht verwendete Spalten gibt, scheint dies für eine neue Tabelle besser geeignet zu sein.

Die erste Tabelle enthält eine Aufzeichnung der Seitenaufrufe (derzeit 2 Millionen Datensätze).

- Ich würde
- IP Adresse
- mal angesehen
- Mit Zeitstempel erstellt
- Datum

Für jede IP-Adresse wird ein Datensatz pro Tag erstellt. Aufeinanderfolgende Seitenaufrufe werden zu den Zeitaufrufen pro Tag hinzugefügt

Zusätzliche Felder für die Herkunftsnachverfolgung (z. B. Google Analytics-Quelle / Medium / Kampagne)

Nicht jeder Besuch wird diese Informationen haben. Ich gehe davon aus, dass ungefähr 10% der Zeilen die Daten enthalten (da diese normalerweise nur beim ersten Besuch zugeordnet werden).

Die Daten werden hauptsächlich verwendet, um die Herkunft der Personen zu bestimmen. Dies wird möglicherweise häufiger verwendet (was sich dann für den einzelnen Tisch zu eignen scheint).

Schätzen Sie das Feedback - können Sie bei Bedarf weitere hinzufügen

cgmckeever
quelle

Antworten:

29

Was Sie kämpfen, ist vertikale Partitionierung. Dies ist eine Entwurfstechnik für physische Datenbanken, um die Leistung zu verbessern. Wie bei jeder Entwurfstechnik für physische Datenbanken hängt ihre Anwendbarkeit von den spezifischen Abfragen ab, die Sie optimieren möchten, und davon, ob diese Technik sie optimieren wird. Aus logischer Sicht sind diese neuen Felder, wenn sie vom Kandidatenschlüssel für Ihre Entität abhängen, Fakten darüber, die zu dieser Entität gehören. Stellen Sie zunächst sicher, dass Sie die funktionale Abhängigkeit dieser neuen Felder von Ihren Kandidatenschlüsseln vollständig verstehen, um sicherzustellen, dass es sich tatsächlich um Fakten zu den täglichen Seitenaufrufen handelt. Wenn dies der Fall ist, ist die Entscheidung, sie in eine andere Tabelle zu partitionieren, eine Leistungsoptimierung, die nur durchgeführt werden sollte, wenn Ihre Leistungsziele erreicht werden.

Im Allgemeinen ist die vertikale Partitionierung hilfreich, wenn Sie diese neuen Spalten nur selten und getrennt von den anderen Spalten in der Originaltabelle abfragen. Durch Platzieren dieser Spalten in einer anderen Tabelle, die dieselbe PK wie Ihre vorhandene Tabelle aufweist, können Sie diese direkt abfragen, wenn Sie diese neuen Spalten benötigen, und einen viel höheren Durchsatz erzielen, da Sie für diese neue Tabelle viel mehr Zeilen pro Seite auf dem Datenträger haben da nicht alle Spalten der Originaltabelle in diesen Zeilen stehen. Wenn Sie diese Spalten jedoch immer zusammen mit den Spalten in der Originaltabelle abfragen, ist eine vertikale Partition wenig sinnvoll, da Sie immer einen Outer Join benötigen, um sie abzurufen. Seiten aus Tabellen auf der Festplatte werden unabhängig voneinander in den Pufferpool eines DBMS aufgenommen, jedoch nie vorverknüpft. und so muss diese Verknüpfung bei jeder Abfrageausführung erfolgen, auch wenn die Daten im Pufferpool angeheftet sind. In diesem Szenario würde es der DBMS-Speicher-Engine ermöglichen, diese NULL-Spalten in der Originaltabelle zu erstellen, um sie effizient zu speichern, wenn sie NULL sind, und die Notwendigkeit des Beitritts beim Abrufen zu beseitigen.

Es klingt für mich so, als wäre Ihr Anwendungsfall der letztere und das Hinzufügen von NULLABLE zu Ihrer Originaltabelle ist der richtige Weg. Aber wie bei allem anderen im Datenbankdesign kommt es darauf an, und um die richtige Entscheidung zu treffen, müssen Sie Ihre erwartete Arbeitsbelastung kennen und wissen, wovon eine gute Wahl abhängt. Ein gutes Beispiel für einen geeigneten Anwendungsfall für die vertikale Partitionierung wäre ein Personen-Suchfenster, in dem Ihre Anwendung einige sehr selten aufgefüllte Informationen zu einer Person enthält, nach der jemand möglicherweise suchen möchte, dies jedoch selten tut. Wenn Sie diese Informationen in eine andere Tabelle einfügen, stehen Ihnen einige gute Leistungsoptionen zur Verfügung. Sie können die Suche so schreiben, dass Sie 2 Abfragen haben - eine, die die wichtigsten, immer ausgefüllten Informationen nur zur Suche verwendet (wie Nachname oder ssn). und eine, bei der Outer die sehr selten aufgefüllten Informationen nur dann zusammenfügt, wenn sie zur Suche angefordert werden. Oder Sie können den DBMS-Optimierer nutzen, wenn er intelligent genug ist, um für einen bestimmten Satz von Hostvariablen zu erkennen, dass der Outer Join nicht benötigt wird und nicht ausgeführt wird. Daher müssen Sie nur eine Abfrage erstellen.

Welche DBMS-Plattform verwenden Sie? Die Art und Weise, in der die Plattform mit dem NULL-Spaltenspeicher umgeht, optimiert Ihre Abfrage sowie die Verfügbarkeit der Unterstützung für Spalten mit geringer Dichte (dies hat SQL Server zur Folge), wirkt sich auf die Entscheidung aus. Letztendlich würde ich empfehlen, beide Entwürfe in einer Testumgebung mit produktionsgroßen Daten und Arbeitslasten auszuprobieren und herauszufinden, welche Ihre Leistungsziele besser erreichen.

Todd Everett
quelle
Mir ist nicht klar, was Sie unter "Wenn Sie diese Spalten jedoch immer zusammen mit den Spalten in der Originaltabelle abfragen, ist eine vertikale Partition nicht sehr sinnvoll, da Sie immer einen Outer Join benötigen, um sie abzurufen." Wenn Sie möchten, dass die Primärspalten unabhängig von der Verfügbarkeit der Sekundärspalten verfügbar sind, müssen Sie nur einen Outer Join ausführen. Andernfalls verwenden Sie einen INNER JOIN. Dies ist in den meisten Fällen von Vorteil (Verringerung der Anzahl der betrachteten Zeilen) ).
jmoreno
Vielen Dank für all die Hilfe hier. Ich habe die Felder hinzugefügt, aber nachdem ich mir das überlegt hatte, sah ich, dass ich ein paar andere Tabellen haben sollte, um alles besser zu identifizieren. Schließlich kam es zu besucher_besuchen (der eine besucher_id hat und die Quelle enthält) seitenaufrufe (der vistor_id und besucher_visit_id hat), da ich genau wissen möchte, welche seitenaufrufe dem besuch zugeordnet sind, habe ich diesen link hinzugefügt. Ich habe ein bisschen damit gerungen, aber ich denke, es war die richtige Entscheidung
jedenfalls
10

Persönlich neige ich dazu, der vorhandenen Tabelle Spalten hinzuzufügen. Der neue Tisch kauft dir eigentlich gar nichts:

  • Sie sparen nicht wirklich viel Speicherplatz, da die NULL-Werte in der ursprünglichen Tabelle keinen Speicherplatz belegen und die neue Tabelle eine Art Bezeichner benötigt, der die Einsparungen ohnehin ausgleicht
  • Ihre Anfragen werden immer komplexer ... where newcolumn is not nullwird einleft outer join

In der einzelnen Tabelle bedeutet dies lediglich, dass Ihre Zeilengröße von Seite zu Seite variieren kann. Dies sollte jedoch nicht viele Ihrer vorhandenen Seiten betreffen, insbesondere wenn sich Ihr Clustered-Index in einer monoton wachsenden Spalte befindet (Identität oder Datum / Uhrzeit).

Aaron Bertrand
quelle
Da die Tabelle derzeit nicht breit ist (basierend auf Ihrer Beschreibung) und diese Daten sie nicht zu breit machen, würde ich zustimmen.
HLGEM
4

Angesichts der von Ihnen bereitgestellten Informationen und nur der allgemeinen Normalisierung als Ziel würde ich wahrscheinlich einfach nullfähige Spalten hinzufügen, aber Sie haben nicht genügend Informationen darüber angegeben, wie die Daten verwendet werden, um zu wissen, wie die Daten am besten modelliert werden können ist.

Je nachdem, wie Sie diese Daten tatsächlich verwenden, möchten Sie möglicherweise ein anderes Datenmodell in Betracht ziehen. Wenn Sie diese Daten für die Berichterstellung verwenden, möchten Sie möglicherweise ein Dimensionsmodell untersuchen, das für bestimmte Berichterstellungstypen effizienter ist. Beispielsweise eignet sich die Tageszeitanalyse gut für eine Aufteilung der Datums- und Zeitdimension.

Bei der Beantwortung von analytischen Fragen wie "Was ist die beliebteste Tageszeit für Besuche von Kampagnen wie X" oder "An welchem ​​Tag einer Kampagne sehen wir die meisten Besuche pro Stunde" funktioniert eine einzelne Datenzeitspalte nicht Sehr gut (aber dies kann sogar in einem relationalen Modell aufgeteilt werden), und es gibt viele Fälle, in denen Sie die IP-Adresse als Dimension behandeln (möglicherweise mit einer Art von Geografiedaten in einer Schneeflocke).

Cade Roux
quelle