it-swarm-eu.dev

Jak spravovat 3,1 miliardy řádků dat?

V současné době mám za úkol implementovat schéma úložiště pro relativně velké množství dat. K datům bude primárně přistupováno za účelem stanovení aktuálního data point hodnota, ale jsem také povinen sledovat posledních šest měsíců historie pro trendy v oblasti dat/analytics.

Byl přidán poslední požadavek na sledování hodnoty min/max/sum za poslední hodinu.

POZNÁMKA: V ideálním případě bych chtěl zvážit možnost MongoDB, ale musím prokázat, že jsem vyčerpal nejprve možnosti serveru SQL.

Data

Následující tabulka představuje primární zdroj dat (nejčastěji dotazované). Tabulka bude mít přibližně pět milionů řádků. Změny dat budou převážně příkazy UPDATE s velmi občasnými příkazy INSERT po prvotním načtení dat. Rozhodl jsem se klastrovat data podle dataPointId, protože budete vždy vybírat 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])
)

Druhá tabulka je výrazně větší na přibližně 3,1 miliardách řádků (což představuje údaje za posledních šest měsíců). Data starší než šest měsíců budou vymazána; jinak striktně příkazy INSERT (~ 200 řádků/s, 720 000 řádků/hodinu, 17 milionů řádků/týden).

// 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])

)

Očekává se, že tato tabulka se zdvojnásobí, protože se počet sledovaných hodnot datových bodů zvyšuje na 400 řádků/s (takže dosažení ~ 10 miliard není vyloučeno).

Otázka (y) (Ano, ptám se více než jedné ... jsou úzce spojeny).

V současné době používám databázi SQL-Server 2008 R2 Standard Edition. Pravděpodobně udělám důvod pro upgrade na Enterprise Edition, pokud dokážu získat požadovanou úroveň výkonu pomocí tabulkových oddílů (nebo MongoDB, pokud nemůžu dosáhnout požadovaných úrovní výkonu s SQL-Serverem). Chtěl bych váš příspěvek k následujícímu:


1) Vzhledem k tomu, že musím vypočítat min, max a sum za poslední hodinu (jako v now - 60 minutes). Jaký je nejlepší přístup pro sledování posledních údajů:

  • Ukládání posledních dat do paměti datové služby. Vypočítat vypočtené min/max/průměr s každým datem UPDATE.

  • Dotaz na nedávnou historii z tabulky historie (dopad na další otázku?) Během každého příkazu UPDATE. Dotaz by měl přístup k nejnovějším datům pro hodnotu datového bodu a měl by být skenován pouze za posledních milion záznamů?

  • Chcete-li se vyhnout vyhledávání tabulky historie, uložte nejnovější historii do samotného řádku DataPointValue. Možná je uložen jako oddělený řetězec a zpracován uvnitř UPDATE proc?

  • Další možnost, kterou jsem neuvažoval?


2) Pro DataPointValueHistory budou dotazy proti datovatelné vždy podle dataPointId a jednoho nebo více valueId. Dotazované údaje budou obvykle za poslední den, týden nebo měsíc, ale v některých případech mohou být úplné šest měsíců.

V současné době vytvářím vzorovou datovou sadu, která má experimentovat s tím, zda má větší smysl seskupování podle dataPointId/valueId/timeStamp nebo timeStamp/dataPointId/valueId. Pokud má někdo zkušenosti s prací s tabulkou takové velikosti a ochotný nabídnout svůj náhled, bylo by to oceněno. Přikláním se k druhé možnosti, abych se vyhnul fragmentaci indexů, ale výkon dotazů je rozhodující.

  • Cluster DataPointValueHistory by dataPointId -> valueId -> timeStamp

  • Cluster DataPointValueHistory by timeStamp -> dataPointId -> valueId


3) Nakonec, jak je uvedeno výše, myslím, že bude rozumné rozdělit tabulku DataPointValueHistory. Jakékoli návrhy, jak nejlépe rozdělit data historie, by se velmi ocenily.

  • Pokud je nejprve seskupeno podle časového razítka, myslím, že data by měla být rozdělena podle týdnů (celkem 27 oddílů). Nejstarší oddíl bude vymazán po 27. týdnu.

  • Pokud je seskupeno dataPointId nejprve, myslím, že data by měla být rozdělena podle nějakého modulu id?

Protože mám velmi omezené zkušenosti s dělením tabulek, byla by vaše odbornost oceněna.

14
Calgary Coder

Tuto analýzu jsem považoval za velmi užitečnou, když jsem zkoumal vytvoření analytického řešení, které by mělo v jedné tabulce miliardy řádků.

http://leiliweb.wordpress.com/2012/12/11/partitioned-table-and-index-strategies-using-sql-server-2008/

4
avakharia