Ich bin derzeit mit der Implementierung eines Speicherschemas für eine relativ große Datenmenge beauftragt. Auf die Daten wird in erster Linie zugegriffen, um einen aktuellen data point
Wert zu bestimmen , aber ich muss auch die letzten sechs Monate des Verlaufs für Datentrends / -analysen nachverfolgen.
Eine kürzliche Forderung wurde hinzugefügt , um das zu verfolgen min
/ max
/ sum
Wert für die letzte Stunde.
ANMERKUNG: Idealerweise würde ich gerne eine MongoDB-Option in Betracht ziehen, aber ich muss zuerst nachweisen, dass ich die SQL-Server-Optionen ausgeschöpft habe.
Die Daten
Die folgende Tabelle stellt die primäre Datenquelle dar (die am häufigsten abgefragt wird). Die Tabelle enthält ungefähr fünf Millionen Zeilen. Bei den Datenänderungen handelt es sich überwiegend um UPDATE
Anweisungen mit sehr gelegentlichen INSERT
Anweisungen nach dem erstmaligen Laden der Daten. Ich habe mich dafür entschieden, die Daten nach zu gruppierendataPointId
da Sie immer auswählen werden all values for a given data point
.
// Simplified Table
CREATE TABLE [dbo].[DataPointValue](
[dataPointId] [int] NOT NULL,
[valueId] [int] NOT NULL,
[timestamp] [datetime] NOT NULL,
[minimum] [decimal](18, 0) NOT NULL,
[hourMinimum] [decimal](18, 0) NOT NULL,
[current] [decimal](18, 0) NOT NULL,
[currentTrend] [decimal](18, 0) NOT NULL,
[hourMaximum] [decimal](18, 0) NOT NULL,
[maximum] [decimal](18, 0) NOT NULL
CONSTRAINT [PK_MeterDataPointValue] PRIMARY KEY CLUSTERED ([dataPointId],[valueId])
)
Die zweite Tabelle ist mit etwa 3,1 Milliarden Zeilen (entsprechend den Daten der letzten sechs Monate) deutlich größer. Daten, die älter als sechs Monate sind, werden gelöscht. ansonsten streng datenINSERT
(~ 200 Zeilen / Sek., 720.000 Zeilen / Stunde, 17 Millionen Zeilen / Woche).
// Simplified Table
CREATE TABLE [dbo].[DataPointValueHistory](
[dataPointId] [int] NOT NULL,
[valueId] [int] NOT NULL,
[timestamp] [datetime] NOT NULL,
[value] [decimal](18, 0) NOT NULL,
[delta] [decimal](18, 0) NOT NULL
CONSTRAINT [PK_MeterDataPointHistory] PRIMARY KEY CLUSTERED ([dataPointId], [valueId], [timestamp])
)
Es wird erwartet, dass sich die Größe dieser Tabelle verdoppelt, wenn die Anzahl der verfolgten Datenpunktwerte auf 400 Zeilen / Sek. Ansteigt (sodass ein Erreichen von ~ 10 Milliarden nicht ausgeschlossen ist).
Die Fragen) (ja, ich stelle mehr als eine Frage ... sie hängen eng zusammen).
Ich verwende derzeit eine SQL Server 2008 R2 Standard Edition-Datenbank. Ich werde wahrscheinlich das Upgrade auf Enterprise Edition in Betracht ziehen, wenn mit Tabellenpartitionen das gewünschte Leistungsniveau erreicht werden kann (oder MongoDB, wenn mit SQL-Server die erforderlichen Leistungsniveaus nicht erreicht werden können). Ich hätte gerne Ihre Beiträge zu folgenden Themen:
1) Da ich brauche das zu berechnen min
, max
und sum
für die vergangene Stunde (wie in now - 60 minutes
). Was ist der beste Ansatz für die Verfolgung aktueller Daten:
Letzte Daten im Speicher des Datendienstes speichern. Schreiben Sie mit jedem Daten-UPDATE den berechneten Min / Max / Mittelwert aus.
Fragen Sie bei jeder UPDATE-Anweisung den aktuellen Verlauf aus der Verlaufstabelle ab (wirkt sich auf die nächste Frage aus?). Eine Abfrage würde auf die neuesten Daten für einen Datenpunktwert zugreifen und sollte nur die letzten Millionen Datensätze durchsuchen oder so?
Den letzten Verlauf in der DataPointValue-Zeile selbst speichern, um das Nachschlagen der Verlaufstabelle zu vermeiden? Vielleicht als begrenzte Zeichenfolge gespeichert und innerhalb des UPDATE-Prozesses verarbeitet?
Andere Option, die ich nicht in Betracht gezogen habe?
2) Für DataPointValueHistory
Abfragen gegen die Daten werden immer von dataPointId
und einer oder mehreren valueId
. Die abgefragten Daten beziehen sich normalerweise auf den letzten Tag, die letzte Woche oder den letzten Monat, in einigen Fällen jedoch auch auf die gesamten sechs Monate.
Ich erstelle gerade einen Beispieldatensatz, um zu testen, ob das Clustering nach dataPointId / valueId / timeStamp oder timeStamp / dataPointId / valueId sinnvoller ist. Wenn jemand Erfahrung mit dem Umgang mit einem Tisch dieser Größe hat und bereit ist, seine Einsicht zu gewähren, wäre er dankbar. Ich neige zu letzterer Option, um eine Indexfragmentierung zu vermeiden, aber die Abfrageleistung ist entscheidend.
Cluster
DataPointValueHistory
nach dataPointId -> valueId -> timeStampCluster
DataPointValueHistory
von timeStamp -> dataPointId -> valueId
3) Schließlich, wie oben erwähnt, halte ich es für sinnvoll, die DataPointValueHistory
Tabelle zu partitionieren . Für Vorschläge zur optimalen Partitionierung der Verlaufsdaten sind wir sehr dankbar.
Wenn zuerst nach Zeitstempel geclustert wird, sollten die Daten nach Woche partitioniert werden (insgesamt 27 Partitionen). Die älteste Partition wird nach der 27. Woche gelöscht.
Wenn zuerst von dataPointId geclustert, denke ich, dass die Daten durch einen Modul der ID partitioniert werden sollten?
Da ich nur sehr wenig Erfahrung mit der Partitionierung von Tabellen habe, würde ich mich über Ihr Fachwissen freuen.
quelle
Antworten:
Ich fand diese Analyse sehr nützlich, als ich über die Erstellung einer Analyselösung nachdachte, die Milliarden von Zeilen in einer Tabelle enthalten würde.
http://leiliweb.wordpress.com/2012/12/11/partitioned-table-and-index-strategies-using-sql-server-2008/
quelle