Effizientes Speichern von Sätzen von Schlüssel-Wert-Paaren mit völlig unterschiedlichen Schlüsseln

9

Ich habe eine Anwendung geerbt, die einer Site viele verschiedene Arten von Aktivitäten zuordnet. Es gibt ungefähr 100 verschiedene Aktivitätstypen, und jeder hat unterschiedliche Sätze von 3-10 Feldern. Alle Aktivitäten haben jedoch mindestens ein Datumsfeld (kann eine beliebige Kombination aus Datum, Startdatum, Enddatum, geplantem Startdatum usw. sein) und ein Feld für die verantwortliche Person. Alle anderen Felder variieren stark und ein Startdatum wird nicht unbedingt als "Startdatum" bezeichnet.

Das Erstellen einer Subtyp-Tabelle für jeden Aktivitätstyp würde zu einem Schema mit 100 verschiedenen Subtyp-Tabellen führen, das zu unhandlich wäre, um es zu behandeln. Die aktuelle Lösung für dieses Problem besteht darin, die Aktivitätswerte als Schlüssel-Wert-Paare zu speichern. Dies ist ein stark vereinfachtes Schema des aktuellen Systems, um den Punkt zu vermitteln.

Geben Sie hier die Bildbeschreibung ein

Jede Aktivität verfügt über mehrere ActivityFields. Jede Site verfügt über mehrere Aktivitäten, und in der SiteActivityData-Tabelle werden die KVPs für jede SiteActivity gespeichert.

Dadurch ist die (webbasierte) Anwendung sehr einfach zu codieren, da Sie lediglich die Datensätze in SiteActivityData für eine bestimmte Aktivität durchlaufen und einem Formular eine Bezeichnung und ein Eingabesteuerelement für jede Zeile hinzufügen müssen. Aber es gibt viele Probleme:

  • Integrität ist schlecht; Es ist möglich, ein Feld in SiteActivityData einzufügen, das nicht zum Aktivitätstyp gehört, und DataValue ist ein Varchar-Feld, sodass Zahlen und Daten ständig umgewandelt werden müssen.
  • Die Berichterstellung und Ad-hoc-Abfrage dieser Daten ist schwierig, fehleranfällig und langsam. Um beispielsweise eine Liste aller Aktivitäten eines bestimmten Typs zu erhalten, deren Enddatum innerhalb eines bestimmten Bereichs liegt, müssen Pivots und Varchars auf Datumsangaben gesetzt werden. Die Verfasser von Berichten HASSEN dieses Schema, und ich beschuldige sie nicht.

Ich suche also nach einer Möglichkeit, eine große Anzahl von Aktivitäten, die fast keine gemeinsamen Felder haben, so zu speichern, dass die Berichterstellung einfacher wird. Was ich mir bisher ausgedacht habe, ist die Verwendung von XML zum Speichern der Aktivitätsdaten in einem Pseudo-NoSQL-Format:

Geben Sie hier die Bildbeschreibung ein

Die Aktivitätstabelle würde die XSD für jede Aktivität enthalten, sodass die ActivityField-Tabelle nicht mehr erforderlich ist. SiteActivity würde das Schlüsselwert-XML enthalten, sodass sich jede Aktivität für eine Site jetzt in einer einzelnen Zeile befindet.

Eine Aktivität würde ungefähr so ​​aussehen (aber ich habe sie nicht vollständig ausgearbeitet):

<SomeActivityType>
  <SomeDateField type="StartDate">2000-01-01</SomeDateField>
  <AnotherDateField type="EndDate">2011-01-01</AnotherDateField>
  <EmployeeId type="ResponsiblePerson">1234</EmployeeId>
  <SomeTextField>blah blah</SomeTextField>
  ...

Vorteile:

  • Die XSD würde das XML validieren und Fehler wie das Einfügen einer Zeichenfolge in ein Zahlenfeld auf Datenbankebene abfangen, was mit dem alten Schema, in dem alles in varchar gespeichert war, unmöglich war.
  • Das Recordset von KVPs, das zum Erstellen der Webformulare verwendet wird, kann problemlos mit reproduziert werden select ... from ActivityXML.nodes('/SomeActivityType/*') as T(r)
  • Eine xpath-Unterabfrage des XML kann verwendet werden, um eine Ergebnismenge zu erstellen, die Spalten für Startdatum, Enddatum usw. enthält, ohne einen Pivot zu verwenden select ActivityXML.value('.[@type=StartDate]', 'datetime') as StartDate, ActivityXML.value('.[@type=EndDate]', 'datetime') as EndDate from SiteActivity where...

Scheint dies eine gute Idee zu sein? Ich kann mir keine anderen Möglichkeiten vorstellen, eine so große Anzahl unterschiedlicher Eigenschaften zu speichern. Ein anderer Gedanke, den ich hatte, war, das vorhandene Schema beizubehalten und es in etwas zu übersetzen, das in einem Data Warehouse leichter abfragbar ist, aber ich habe noch nie ein Sternschema entworfen und hätte keine Ahnung, wo ich anfangen soll.

Zusätzliche Frage: Wenn ich ein Tag mit einem Datumsdatentyp in der XSD definiere xs:date, wird SQL Server es dann als Datumswert indizieren? Ich bin besorgt, wenn ich nach Datum abfrage, muss die Datumszeichenfolge in einen Datumswert umgewandelt werden, und es besteht keine Chance, einen Index zu verwenden.

Paul Abbott
quelle
Wie aktuell müssen die Daten für die Berichte sein? Werden die Berichte die Produktion erreichen?
James Anderson
Die meisten Berichte treffen jetzt auf ein Data Warehouse (das eigentlich kein DW ist, sondern im Wesentlichen eine Kopie des Produktionstransaktionsschemas mit einer Vielzahl von Ansichten und Tabellen aus anderen hinzugefügten Datenbanken). Berichte, die einen Tag veraltet sind, sind akzeptabel, aber es wäre ein Bonus, wenn sie live sein könnten.
Paul Abbott
Wie viel Überlappung gibt es in den Feldern? Decken zehn Felder alle 100 Untertypen ab, oder gibt es ~ 500 völlig unterschiedliche Felder?
Jon of All Trades
Es gibt 72 Felder und 75 Aktivitätsarten. 30 Felder werden nur von einer Aktivität verwendet, und die meisten anderen Felder werden von 5-10 Aktivitäten verwendet. Es gibt eine Handvoll Felder, die von ~ 30 verschiedenen Aktivitäten verwendet werden. Zum größten Teil gibt es nicht viel Gemeinsamkeit zwischen den Aktivitäten.
Paul Abbott

Antworten:

7

Ich suche also nach einer Möglichkeit, eine große Anzahl von Aktivitäten, die fast keine gemeinsamen Felder haben, so zu speichern, dass die Berichterstellung einfacher wird.

Nicht genug Repräsentanten, um zuerst einen Kommentar abzugeben, also los geht's!

Wenn der Hauptzweck die Berichterstellung ist und Sie ein DW haben (auch wenn es kein Sternschema ist), würde ich empfehlen, dies in ein Sternschema zu integrieren. Die Vorteile sind schnelle, einfache Abfragen. Der Nachteil ist ETL, aber Sie erwägen bereits, die Daten in ein neues Design zu verschieben, und ETL in Star-Schema ist wahrscheinlich einfacher zu erstellen und zu warten als eine XML-Wrapper-Lösung (und SSIS ist in Ihrer SQL Server-Lizenzierung enthalten). Außerdem wird der Prozess eines anerkannten Berichts- / Analysedesigns gestartet.

Also, wie das geht ... Es hört sich so an, als hätten Sie einen so genannten Factless Fact . Dies ist eine Schnittmenge von Attributen, die ein Ereignis ohne zugehörige Kennzahl definieren (z. B. einen Verkaufspreis). Sie haben Termine für einige oder alle Ihrer Aktivitäten? Wahrscheinlich sollten Sie wirklich einen Schnittpunkt zwischen Aktivität, Site und Datum (en) haben.

DimActivity- Ich vermute, es gibt ein Muster, mit dem Sie diese in mindestens relativ gemeinsam genutzte Spalten aufteilen können. Wenn ja, haben Sie vielleicht drei? fünf? Dimensionen für Klassen von Aktivitäten. Im schlimmsten Fall haben Sie einige konsistente Spalten, z. B. den Aktivitätsnamen, nach denen Sie filtern können, und Sie belassen allgemeine Überschriften wie "Attribut1" usw. für die verbleibenden zufälligen Details.

Sie benötigen nicht alles in der Dimension - es sollte (wahrscheinlich) keine Daten in der Aktivitätsdimension geben - sie sollten alle in der Tatsache enthalten sein, da der Ersatzschlüssel auf die Datumsdimension verweist. Ein Datum, das in einer Personendimension verbleiben würde, wäre beispielsweise ein Geburtsdatum, da es ein Attribut einer Person ist. Ein Krankenhausbesuchsdatum würde in einer Tatsache liegen, da es sich unter anderem um ein Zeitpunktereignis handelt, das mit einer Person verbunden ist, aber es ist kein Attribut der Person, die das Krankenhaus besucht. Mehr Datumsdiskussion in der Tat.

DimSite- scheint einfach zu sein, daher werden wir hier die Ersatzschlüssel beschreiben. Im Wesentlichen ist dies nur eine inkrementelle, eindeutige ID. Die Spalte Integer Identity ist häufig. Dies ermöglicht die Trennung von DW- und Quellsystemen und stellt optimale Verknüpfungen im Data Warehouse sicher. Ihr natürlicher Schlüssel oder Geschäftsschlüssel wird normalerweise aufbewahrt, aber für Wartung / Design nicht analysiert und verbunden. Beispielschema:

CREATE TABLE [DIM].[Site]
(
 SiteSK INT NOT NULL IDENTITY PRIMARY KEY
,SiteNK INT NOT NULL --source system key
,SiteName VARCHAR(500) NOT NULL
)

DimDate- Datumsattribute. Machen Sie einen "Smart Key" anstelle einer Identität. Dies bedeutet, dass Sie eine aussagekräftige Ganzzahl eingeben können, die sich auf ein Datum für Abfragen wie WHERE DateSK = 20150708 bezieht. Es gibt viele kostenlose Skripte zum Laden von DimDate, und die meisten enthalten diesen Smart Key. ( eine Option )

DimEmployee - Ihr XML enthielt dies, wenn es sich um eine allgemeinere Änderung von DimPerson handelt, und füllen Sie relevante Personenattribute aus, sobald diese verfügbar und für die Berichterstellung relevant sind.

Und Ihre Tatsache ist:

FactActivitySite
DimSiteSK - FK to DimSite
DimActivitySK - FK to DimActivity
DimEmployee - FK to DimEmployee
DimDateSK - FK to DimDate

Sie können diese im Fakt umbenennen und Sie können mehrere Datumsschlüssel pro Ereignis haben. Die Fakten sind in der Regel sehr umfangreich. Daher ist es in der Regel gut, Aktualisierungen zu vermeiden. Wenn Sie mehrere Datumsaktualisierungen für ein einzelnes Ereignis haben, möchten Sie möglicherweise ein Löschen / Einfügen-Design ausprobieren, indem Sie der Tatsache einen SK hinzufügen, mit dem Sie die Zeile "Aktualisieren" auswählen können gelöscht werden und dann die neuesten Daten einfügen.

Erweitern Sie Ihre Faktendaten auf das, was Sie benötigen : StartDateSK, EndDateSK, ScheduledStartDateSK.

Alle Dimensionen sollten eine unbekannte Zeile haben, normalerweise mit einem fest codierten -1 SK. Wenn Sie die Tatsache laden und eine Aktivität keines der enthaltenen Daten enthält, sollte sie einfach eine -1 laden.

Die Tatsache ist eine Sammlung von ganzzahligen Verweisen auf Ihre Attribute, die in den Dimensionen gespeichert sind. Fügen Sie sie zusammen und Sie erhalten alle Ihre Details in einem sehr sauberen Verknüpfungsmuster. Die Tatsache ist aufgrund der Datentypen außergewöhnlich klein und schnell. Da Sie sich in SQL Server befinden, fügen Sie einen Columnstore-Index hinzu , um die Leistung weiter zu steigern. Sie können es einfach löschen und während der ETL neu erstellen. Sobald Sie SQL 2014+ erreicht haben, können Sie in Columnstore-Indizes schreiben.

Geben Sie hier die Bildbeschreibung ein

Wenn Sie diesen Weg gehen, suchen Sie nach Dimensional Modeling. Ich würde die Kimball-Methode empfehlen . Es gibt auch viele kostenlose Anleitungen, aber wenn dies etwas anderes als eine einmalige Lösung ist, lohnt sich die Investition wahrscheinlich.

Dave
quelle
(Frage von wesdev): @ Dave, welches ERD-Tool haben Sie verwendet?
Ypercubeᵀᴹ
Dies wurde in Microsoft Visio 2013
Dave