it-swarm.com.de

Wie verwalte ich 3,1 Milliarden Datenzeilen?

Ich bin derzeit damit beauftragt, ein Speicherschema für eine relativ große Datenmenge zu implementieren. Auf die Daten wird hauptsächlich zugegriffen, um einen aktuellen data point - Wert zu ermitteln. Ich muss jedoch auch die letzten sechs Monate des Verlaufs für Datentrends/-analysen verfolgen.

Eine kürzlich erfolgte Anforderung wurde hinzugefügt, um den Wert min/max/sum für die letzte Stunde zu verfolgen.

HINWEIS: Idealerweise möchte ich eine MongoDB-Option in Betracht ziehen, aber ich muss nachweisen, dass ich zuerst die SQL-Server-Optionen ausgeschöpft habe.

Die Daten

Die folgende Tabelle stellt die primäre Datenquelle dar (am häufigsten abgefragt). Die Tabelle wird ungefähr fünf Millionen Zeilen enthalten. Die Datenänderungen sind überwiegend UPDATE Anweisungen mit sehr gelegentlichen INSERT Anweisungen nach dem anfänglichen Laden der Daten. Ich habe mich dafür entschieden, die Daten nach dataPointId zu gruppieren, da Sie immer all values for a given data point Auswählen werden.

// 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 ungefähr 3,1 Milliarden Zeilen (die Daten der letzten sechs Monate darstellen) deutlich größer. Daten, die älter als sechs Monate sind, werden gelöscht. ansonsten streng Daten INSERT Anweisungen (~ 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/s ansteigt (ein Erreichen von ~ 10 Milliarden kommt also nicht in Frage).

Die Frage (n) (Ja, ich frage mehr als eine ... sie sind alle eng miteinander verbunden).

Ich verwende derzeit eine SQL-Server 2008 R2 Standard Edition-Datenbank. Ich werde mich wahrscheinlich für ein Upgrade auf Enterprise Edition aussprechen, 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 möchte Ihre Beiträge zu folgenden Themen:


1) Vorausgesetzt, ich muss die min, max und sum für die letzte Stunde berechnen (wie in now - 60 minutes). Was ist der beste Ansatz zur Verfolgung aktueller Daten:

  • Halten Sie die letzten Daten im Speicher des Datendienstes. Schreiben Sie mit jedem Daten-UPDATE den berechneten Min/Max/Durchschnitt aus.

  • Fragen Sie während jeder UPDATE-Anweisung den aktuellen Verlauf aus der Verlaufstabelle ab (wirkt sich auf die nächste Frage aus?). Die Abfrage würde auf die neuesten Daten für einen Datenpunktwert zugreifen und sollte nur die letzten Millionen Datensätze oder so scannen?

  • Speichern Sie den aktuellen Verlauf in der DataPointValue-Zeile selbst, um die Suche nach Verlaufstabellen zu vermeiden. Möglicherweise als begrenzte Zeichenfolge gespeichert und im UPDATE-Prozess verarbeitet?

  • Andere Option, die ich nicht in Betracht gezogen habe?


2) Für DataPointValueHistory werden Abfragen für die Datentabelle immer von dataPointId und einem oder mehreren valueId durchgeführt. Die abgefragten Daten beziehen sich normalerweise auf den letzten Tag, die letzte Woche oder den letzten Monat, in einigen Fällen jedoch auf die gesamten sechs Monate.

Ich generiere derzeit einen Beispieldatensatz, um zu experimentieren, ob es sinnvoller ist, nach dataPointId/valueId/timeStamp oder timeStamp/dataPointId/valueId zu gruppieren. Wenn jemand Erfahrung im Umgang mit einem Tisch dieser Größe hat und bereit ist, seinen Einblick zu gewähren, wäre er dankbar. Ich neige zu letzterer Option, um eine Indexfragmentierung zu vermeiden, aber die Abfrageleistung ist entscheidend.

  • Cluster DataPointValueHistory von dataPointId -> valueId -> timeStamp

  • Cluster DataPointValueHistory nach timeStamp -> dataPointId -> valueId


3) Schließlich halte ich es, wie oben erwähnt, für sinnvoll, die Tabelle DataPointValueHistory zu partitionieren. Vorschläge zur optimalen Partitionierung der Verlaufsdaten sind sehr willkommen.

  • Wenn zuerst nach Zeitstempel geclustert, denke ich, dass die Daten nach Wochen partitioniert werden sollten (insgesamt 27 Partitionen). Die älteste Partition würde nach Woche 27 gelöscht.

  • Wenn zuerst von dataPointId geclustert, denke ich, dass die Daten durch einen Modul der ID partitioniert werden sollten?

Da ich nur sehr begrenzte Erfahrung mit der Partitionierung von Tabellen habe, wäre Ihr Fachwissen willkommen.

14
Calgary Coder

Ich fand diese Analyse sehr nützlich, als ich nach einer Analyselösung suchte, 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/

4
avakharia