31億行のデータを管理する方法は?


14

私は現在、比較的大量のデータ用のストレージスキーマの実装を担当しています。データは主に現在のdata point値を判断するためにアクセスされますが、データの傾向分析のために過去6か月の履歴を追跡する必要もあります。

最近の要件は、過去1時間のmin/ max/ sum値を追跡するために追加されました。

注:理想的には、MongoDBオプションを検討したいと思いますが、最初にSQL-Serverオプションを使い果たしたことを示す必要があります。

データ

次の表は、プライマリデータソース(最も頻繁にクエリされる)を表しています。テーブルには約500万行が含まれます。データの変更は主に、初期データのロード後のUPDATE非常に不定期のINSERTステートメントを伴うステートメントになります。dataPointIdあなたがいつも選択するので、私はデータをクラスタリングすることを選びました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])
)

2番目のテーブルは、約31億行と著しく大きくなっています(過去6か月のデータを表します)。6か月以上前のデータは削除されます。それ以外の場合は厳密にデータINSERTステートメント(最大200行/秒、720,000行/時間、1700万行/週)。

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

予想されるのは、追跡されるデータポイント値の数が400行/秒に増えると、このテーブルのサイズが2倍になることです(したがって、約100億に達することは問題ではありません)。

質問(はい、私は複数質問しています...それらはすべて密接に関連しています)。

現在、SQL-Server 2008 R2 Standard Editionデータベースを使用しています。テーブルパーティションで目的のパフォーマンスレベルを取得できる場合(またはSQL-Serverで必要なパフォーマンスレベルに到達できない場合はMongoDB)、Enterprise Editionにアップグレードする場合を考えます。以下についてご意見をお寄せください。


1)私は計算する必要があることを考えるとminmaxおよびsum過去1時間(のようにnow - 60 minutes)。最近のデータを追跡するための最良のアプローチは何ですか:

  • データサービスのメモリに最近のデータを保持します。更新された各データで計算された最小/最大/平均を書き出します。

  • 各UPDATEステートメント中に、履歴テーブルから最近の履歴を照会します(次の質問に影響しますか?)。クエリは、データポイント値の最新データにアクセスするため、最後の100万レコード程度をスキャンするだけですか?

  • 履歴テーブルの参照を回避するために、DataPointValue行自体に最近の履歴を保存しますか?おそらく区切られた文字列として保存され、UPDATE proc内で処理されますか?

  • 私が検討していない他のオプション?


2)の場合DataPointValueHistory、データベースに対するクエリは常にby dataPointIdおよび1つ以上valueIdです。クエリされるデータは、通常、最後の日、週、または月になりますが、場合によっては6か月全体になります。

現在、dataPointId / valueId / timeStampまたはtimeStamp / dataPointId / valueIdでクラスター化する方が適切かどうかを試すためのサンプルデータセットを生成しています。このサイズのテーブルを扱った経験があり、洞察を提供したいと思っている人がいれば幸いです。インデックスの断片化を回避するために後者のオプションに傾いていますが、クエリのパフォーマンスは重要です。

  • クラスタDataPointValueHistory> valueId - - > timeStampにdataPointIdによって

  • クラスタDataPointValueHistory> dataPointId - - > valueIdタイムスタンプで


3)最後に、上で述べたように、DataPointValueHistoryテーブルを分割することは理にかなっていると思います。履歴データを最適に分割する方法に関する提案は大歓迎です。

  • 最初にタイムスタンプでクラスター化された場合、データは週ごとにパーティション分割する必要があると考えています(合計27パーティション)。最も古いパーティションは、27週後に削除されます。

  • 最初にdataPointIdによってクラスター化された場合、データはidのモジュラスによって分割されるべきだと考えていますか?

テーブルパーティション分割の経験は非常に限られているため、専門知識をいただければ幸いです。


StackOverflowでこの質問のバージョンを削除しましたか?
タリン

@bluefeet-はい、トピック外としてフラグが付けられました...そこで、SOの質問を削除して、ここで再作成しました(移行されるのをおそらく待っていたはずです)。
カルガリーコーダー

問題ありません。質問がクロスポストされていないことを確認しただけです。
タリン

Standard Editionでは、パーティションビューと複数のベーステーブルを使用してデータをパーティション分割できます。あなたがそれを検討したかどうかはわかりません。
ジョンセイゲル

@Jon-はい、手動のテーブルパーティションを検討しました(その特定の選択は、エンタープライズライセンスが利用可能かどうかに基づいて行われます...はいの場合、なぜ自分の役割になりますか)。
カルガリーコーダー

回答:


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.