Welches dieser Tischdesigns ist für die Leistung besser?


16

Ich wurde gebeten, etwas zu erstellen, das die täglichen Kosten für das Sammeln auf Konten protokolliert, und ich versuche, ein Datenbanktabellenschema zu finden, das dies unterstützt.

Folgendes weiß ich

  • Das Unternehmen hat über 2,5 Millionen Konten
  • Davon arbeiten sie derzeit durchschnittlich 200.000 pro Monat (dies ändert sich mit dem Personalbestand, der derzeit niedrig ist).
  • Sie haben 13 verschiedene Kostentypen, die sie verfolgen möchten, und sie haben gewarnt, dass sie in Zukunft weitere hinzufügen könnten
  • Sie möchten, dass die Kosten täglich nachverfolgt werden
  • Die Kosten werden nicht auf das gesamte Inventar aufgeteilt. Sie sind entweder auf die Anzahl der Konten aufgeteilt, die pro Monat bearbeitet werden (200.000), oder Benutzer können Konto-IDs eingeben, um Kosten auf eine Gruppe von Konten anzuwenden, oder sie können einfach angeben, auf welche Konten die Kosten angewendet werden sollen.

Mein erster Gedanke war eine normalisierte Datenbank:

AccountId
Datum
CostTypeId
Menge

Mein Problem dabei ist, machen Sie die Mathematik. Dieser Tisch wird schnell riesig. Angenommen, alle 13 Kostentypen werden für den aktuellen Monat auf alle bearbeiteten Konten angewendet 200k * 13 * N days in month, entspricht dies etwa 75 bis 80 Millionen Datensätzen pro Monat oder nahezu einer Milliarde Datensätzen pro Jahr.

Mein zweiter Gedanke war, es ein bisschen zu denormalisieren

AccountId
Datum
Gesamtkosten
CostType1
CostType2
CostType3
CostType4
CostType5
CostType6
CostType7
CostType8
CostType9
CostType10
CostType11
CostType12
CostType13

Diese Methode ist denormalisierter und kann bis zu 6 Millionen Datensätze pro Monat ( 200k * N days in month) oder etwa 72 Millionen pro Jahr erstellen. Dies ist viel weniger als die erste Methode. Wenn sich das Unternehmen jedoch in Zukunft für einen neuen Kostentyp entscheidet, muss eine weitere Datenbankspalte hinzugefügt werden.

Welche der beiden Methoden bevorzugen Sie? Warum? Gibt es eine andere Alternative, die dies besser bewältigen könnte?

Am meisten interessiert mich die Berichterstattung über die Leistung, sowohl über zusammengefasste als auch über detaillierte Berichte. Der Job, der die Kosten auf die Konten verteilt, wird jede Nacht ausgeführt, wenn niemand in der Nähe ist. Ein sekundäres Anliegen ist die Datenbankgröße. Die vorhandene Datenbank ist bereits fast 300 GB groß, und ich glaube, der Speicherplatz auf der Festplatte beträgt etwa 500 GB.

Die Datenbank ist SQL Server 2005


Also hol noch eine Platte. Festplatten sind billig. Sie können 2 TB für die Kosten eines Meetings haben, um darüber zu streiten.

Antworten:


9

Eine Milliarde Platten pro Jahr sind nicht viel.

Mit Partitionierung (pro Kostenart vielleicht) und Archivierung ist es verwaltbar.

Die Anzahl der zu speichernden Datenelemente beträgt immer noch 200.000 * 13 * N. Als Spalten erhalten Sie weniger Zeilen pro Seite und es wird mehr Platz benötigt als als Zeilen. Sie können gewinnen, wenn "CostType1" kein Datentyp mit fester Länge ist, aber es ist marginal.

"KISS" wie sie sagen


3
@ Rachel Ich würde definitiv empfehlen, ein Partitionierungsschema mit einem so großen Datensatz zu implementieren. Wenn sie sich auf die monatliche Arbeit und Berichterstellung konzentrieren, ist es am besten, einen Partitionsschlüssel zu wählen, der mit dieser Einstellung übereinstimmt. Wenn Sie Ihre Partition ordnungsgemäß konfigurieren, können Sie Daten einfach in die Tabelle und aus der Tabelle in die Staging-Tabellen verschieben, wodurch umfangreiche Datenladevorgänge und Löschvorgänge für rollierende Datensätze einen Moment dauern, der Sekunden statt Stunden in Anspruch nimmt.
David

6

In diesem Fall würde ich mich mehr auf Indizes konzentrieren, einschließlich der Abdeckung von Indizes nach Bedarf. Ich würde mir auch einige der Tools ansehen, die SQL Server für den Umgang mit sehr großen Tabellen bereitstellt, z. B. die Tabellenpartitionierung.

Stellen Sie sich das so vor, obwohl die Tabelle 80 Milliarden Datensätze enthält, werden die Datensätze, an denen Sie tatsächlich interessiert sind, bei richtiger Indizierung physisch auf der Festplatte zusammengefasst. Aufgrund der Art und Weise, wie Daten in SQL Server organisiert sind, können sich nach Indexgrenzen aufgeteilte Daten auch in einer anderen Tabelle befinden, da nicht die gesamte Tabelle gelesen werden muss, um die erforderlichen Informationen zu erhalten.

Wenn Sie die Tabelle auch partitionieren, können Sie die Zugriffszeit und die Einfügezeit verbessern.


4

Ich würde mich normalisieren. Wir haben die Kostenrechnung für die Rentabilität von Kundenkonten bei einer Bank durchgeführt und mit Hunderten von Treibern, die monatlich über Millionen von Konten nach Kostenstelle oder Hauptbuch oder nach verschiedenen anderen Techniken zugeordnet wurden, über 250 Millionen Zeilen von Einzelkosten generiert.

Zum Beispiel wurden die Gesamtkosten für die Wartung von Geldautomaten auf Konten aufgeteilt, die Geldautomaten verwendet hatten, basierend auf der relativen Nutzungsmenge. Wenn also 1 Million US-Dollar für die Wartung von Geldautomaten ausgegeben wurden und nur 5 Kunden diese jeweils einmal und ein Kunde sie fünfmal verwendeten, kostete dieser eine Kunde die Bank 0,5 Millionen US-Dollar und der andere die Bank jeweils 0,1 Millionen US-Dollar. Andere Treiber könnten sehr viel komplexer sein.

Letztendlich werden Sie wahrscheinlich feststellen, dass es spärlich ist - bestimmte Konten bekommen keine Kosten von bestimmten Quellen / Treibern - und einige Konten bekommen nichts. In einem normalisierten Modell existieren diese Zeilen nicht. Im denormalisierten Modell ist die Zeile mit einigen leeren Spalten vorhanden. Außerdem sollte sich in einem spärlich normalisierten Modell die Leistung verbessern, da das Vorhandensein einer Zeile in der Regel schneller überprüft werden kann (mit deckendem Index für CostType) als das Überprüfen aller Zeilen mit Nicht-NULL in einem bestimmten "Bucket" (auch mit Indizes für jede Betragsspalte - die Sie sehen können, beginnen sehr verschwenderisch zu werden).


SPARSE - Dies ist ein sehr guter Punkt, der den Unterschied ausmacht. Wenn es dünn ist, sparen Sie Platz durch Normalisieren. Ansonsten nicht. Aber Speicherplatz ist billig, deshalb stimme ich persönlich für maximale Flexibilität (normalisiert).

3

Ungeachtet des Leistungsvorteils würde ich mich definitiv für Option 1 entscheiden. Option 2 würde meiner Meinung nach Peter berauben, um Paul zu bezahlen.


2

Ich entschied mich für Option 1, und wenn die Berichtsgeschwindigkeit später zu einem Problem wurde, fügte ich Tabelle 2 hinzu und füllte sie in einer Art automatisiertem Übernacht- / Off-Peak-Prozess in eine Berichtsdatenbank ein.

Sie können dann auch erwägen, die tägliche Tabelle-2-Struktur in weitere wöchentliche, monatliche, vierteljährliche und jährliche Rollups umzuwandeln, falls dies gerechtfertigt ist.

Aber wie gesagt, ich würde mich auch dafür entscheiden, die "Rohdaten" in der richtigen (normalisierten) Form zu speichern.


0

In Anbetracht der von Ihnen erwähnten Mengen würde ich die zweite Option wählen, jedoch ohne TotalCost. Man könnte sagen, das ist noch normalisiert.


Bearbeiten: Alternativ und abhängig von Ihren Anforderungen und der Größe der Konto-ID können Sie auch Folgendes berücksichtigen:

AccountDate
-----------
AccountId  
Date  
AcDtID (surrogate key)

Costs
-------
AcDtID
CostTypeId  
Amount  

Mit diesem Entwurf können Sie der ersten Tabelle immer noch eine denormalisierte TotalCost hinzufügen und diese nachts neu berechnen lassen, sodass einige Berichte nur für die erste Tabelle ausgeführt werden können.


Ich habe TotalCostda drin, weil der Großteil der Berichterstattung zusammengefasst ist, und ich dachte, es wäre schneller, einen einzelnen Wert abzufragen, als 13 verschiedene Werte hinzuzufügen.

Wahrscheinlich, aber dann führen Sie wirklich eine transitiven Abhängigkeit ein. Werden diese Aufzeichnungen jemals aktualisiert? oder einfach geschrieben und dann erst gelesen?

Die Datensätze werden aktualisiert, wenn für diesen Zeitraum neue Kosten anfallen. Nach ungefähr einem Monat ist es unwahrscheinlich, dass die Gesamtkosten aktualisiert werden, aber es ist immer noch möglich, weil beispielsweise jährliche Supportgebühren anfallen.

In diesem Fall sind für jede Aktualisierung zwei Aktualisierungen erforderlich, und das Feld "TotalCost" birgt das Risiko von Inkonsistenzen.

Transitive Abhängigkeit, aber nicht unbedingt das Risiko von Inkonsistenzen - eine CHECK () - Einschränkung kann garantieren, dass TotalCost immer die Summe der Kosten ist.
Mike Sherrill "Cat Recall"

0

Sie sollten die firs-Tabelle tatsächlich in zwei Tabellen unterteilen, damit Sie eine Unterabfrage verwenden und die zweite Zeile als Spalte oder viele Spalten auswählen können. Auf diese Weise ist es flexibler und auf diese Weise können Sie ein Ergebnis wie das zweite leichter erhalten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.