数十億行に最適なデータストア


87

数十億のレコード(1年間で約30億/月)の小さなデータ(約50〜75バイト)を保存できる必要があります。

唯一の要件は、同じGUIDを持つすべてのレコードの高速挿入と高速ルックアップ、および.netからデータストアにアクセスする機能です。

私はSQLサーバーの担当者であり、SQL Serverでこれ実行できると思いますが、BigTable、CouchDB、およびその他のnosqlソリューションについてのすべての話を踏まえると、分散クエリとスケーリング。私はcassandraを試しましたが、.netライブラリは現在コンパイルされていないか、すべて変更される可能性があります(cassandra自体と一緒に)。

利用可能な多くのnosqlデータストアを調べましたが、堅牢な本番環境対応プラットフォームとしてのニーズを満たすものが見つかりません。

.netからアクセスできるように、360億の小さくてフラットなレコードを保存する必要がある場合、何を選択し、その理由を教えてください。


ええ、私の番号は正しいです。現在、これだけ多くのデータがシステムに送られていますが、それを集計して集計カウントのみを保存するため、レコードごとのデータが失われ、1時間ごとのデータの合計のみが維持されます。ビジネス要件のため、各レコードを最初に発生したとおりに維持したいと考えています。これは、月に30億行です。
Jody Powlette 2010年

あなたはいくつかの良い質問を提起しました。答えは次のとおりです。95%の稼働時間で十分です。データはすでに可変量遅延しているため、とにかく事後に同期する必要があるため、短時間ダウンしても問題はありません。インサートを失ったり、何千ものインサートを失ったりすることは、世界の終わりではありません。ただし、1日分のデータを失うことはかなり悪いことです。一貫性もそれほど重要ではありません。基本的に、1日に30Mil行を挿入した後、同じGUID(おそらく20行)ですべての行をフェッチする必要があり、すべてを取り戻すことが合理的に確実です。
Jody Powlette 2010年

毎日/毎時スケジュールされたバッチジョブで1日に3,000万行をダンプしますか、それとも一度に1つずつ一定の流れで発生しますか?
Remus Rusanu 2010年

データはFTPサイトから到着します...ファイルは継続的に受信され、ファイルを解析するプロセスがあり、現在、集約データを生成し、集約値(おそらく1000行)をトランザクションとして挿入します。新しいプロセスでは、到着する各ファイルから数十万行を挿入する必要があります。おそらく、一括挿入を使用するのが最も効率的な方法です。
Jody Powlette 2010年

これは、SSISとSQLServerのETLジョブのように聞こえます。2TB /時間以上のアップロード速度でETLの世界記録を保持しています:blogs.msdn.com/sqlperf/archive/2008/02/27/etl-world-record.aspx
Remus Rusanu 2010年

回答:


103

最大3.5TBのデータを保存し、約1K /秒を24時間365日挿入し、指定されていないレートでクエリを実行することもSQL Serverで可能ですが、さらに質問があります。

  • これにはどのような可用性要件がありますか?99.999%の稼働時間、または95%で十分ですか?
  • どのような信頼性要件がありますか?インサートがない場合、100万ドルかかりますか?
  • どのような回復可能性の要件がありますか?ある日のデータを失った場合、それは重要ですか?
  • どのような一貫性の要件がありますか?書き込みは、次の読み取りで表示されることを保証する必要がありますか?

私が強調したこれらすべての要件が必要な場合、提案する負荷は、どのようなギミック(シャーディング、パーティショニングなど)を試しても、リレーショナルシステム、任意のシステムで数百万のハードウェアとライセンスを必要とします。nosqlシステムは、その定義上、満たすことができません。これらすべての要件をいる

したがって、明らかに、これらの要件のいくつかはすでに緩和されています。Visual Guide to NoSQL Systemsには、「3つのうち2つを選択」パラダイムに基づいてnosql製品を比較する優れたビジュアルガイドがあります。

nosqlの比較

OPコメント更新後

SQL Serverを使用すると、これは簡単な実装になります。

  • 1つの単一テーブルクラスター(GUID、時間)キー。はい、断片化されますが、断片化は先読みに影響し、先読みは重要な範囲のスキャンにのみ必要です。特定のGUIDと日付範囲のみをクエリするため、断片化はそれほど重要ではありません。はい、は幅の広いキーであるため、リーフ以外のページではキー密度が低くなります。はい、それは貧弱なフィルファクターにつながります。はい、ページ分割が発生する可能性があります。これらの問題にもかかわらず、要件を考えると、依然として最良のクラスター化されたキーの選択です。
  • 自動スライディングウィンドウを介して、期限切れのレコードの効率的な削除を実装できるように、テーブルを時間で分割します。先月のオンラインインデックスパーティションの再構築でこれを強化し、GUIDクラスタリングによって導入された不十分なフィルファクターと断片化を排除します。
  • ページ圧縮を有効にします。最初にGUIDによってクラスター化されたキーグループが作成されるため、GUIDのすべてのレコードが隣り合って、次のようになります。ページ圧縮に辞書圧縮を展開する良い機会がます
  • ログファイルには高速IOパスが必要です。ログが1K挿入/秒に追いつくための低遅延ではなく、高スループットに関心があるため、ストリッピングは必須です。

パーティショニングとページ圧縮にはそれぞれEnterpriseEdition SQL Serverが必要であり、Standard Editionでは機能せず、どちらも要件を満たすために非常に重要です。

ちなみに、レコードがフロントエンドWebサーバーファームからのものである場合は、各WebサーバーにExpressを配置し、バックエンドにINSERTを使用する代わりにSEND、ローカル接続/トランザクションを使用してバックエンドに情報を送信します。Webサーバーと同じ場所にあるExpress上。これにより、ソリューションの可用性に関するストーリーが大幅に向上します。

これがSQLServerでのやり方です。良いニュースは、直面する問題がよく理解されており、解決策がわかっていることです。これは、Cassandra、BigTable、Dynamoで達成できるものよりも優れているとは限りません。私は誰かに、彼らの主張を議論するために、SQLっぽくないことについてもっと知識があるようにします。

プログラミングモデル、.Netサポートなどについては触れなかったことに注意してください。正直なところ、大規模な展開では無関係だと思います。それらは開発プロセスに大きな違いをもたらしますが、一度展開されると、ORMオーバーヘッドがパフォーマンスを低下させる場合、開発がどれほど速くても問題ありません:)


Nathanのサイトをホットリンクしましたが、これはスラッシュドットのフロントページではありません;)
Remus Rusanu 2010年

@RemusRusanu:dba.seの移行を見てください。ただ、あなたの準備:-)そして+1する
GBN

Microsoft SQL Server 2016以降、テーブルパーティショニングはSQL Server 2016のほぼすべてのエディションで利用できるようになったため、エンタープライズエディションはテーブルパーティショニングに必要なくなりました。
TChadwick19年

17

一般に信じられていることとは異なり、NoSQLはパフォーマンスやスケーラビリティについてではありません。これは主に、いわゆるオブジェクトリレーショナルインピーダンスの不一致を最小限に抑えることですが、水平方向のスケーラビリティとRDBMSのより一般的な垂直方向のスケーラビリティについても説明します。

高速挿入と高速ルックアップの単純な要件については、ほとんどすべてのデータベース製品で十分です。リレーショナルデータや結合を追加したい場合、または強制する必要のある複雑なトランザクションロジックや制約がある場合は、リレーショナルデータベースが必要です。NoSQL製品は比較できません。

スキーマレスデータが必要な場合は、MongoDBやCouchDBなどのドキュメント指向データベースを使用することをお勧めします。緩いスキーマがこれらの主な魅力です。私は個人的にMongoDBが好きで、いくつかのカスタムレポートシステムで使用しています。データ要件が絶えず変化しているときに非常に便利だと思います。

他の主要なNoSQLオプションは、BigTableやCassandraなどの分散型Key-Valueストアです。これらは、コモディティハードウェアを実行している多くのマシン間でデータベースを拡張する場合に特に役立ちます。もちろん、サーバーでも問題なく動作しますが、ハイエンドのハードウェアや、SQL Server、Oracle、または垂直用に設計されたその他のデータベースを利用していません。スケーリングを利用していません。また、明らかに、リレーショナルではなく、正規化の実施には適していません。または制約。また、お気づきのように、.NETサポートはせいぜいむらがある傾向があります。

すべてのリレーショナルデータベース製品は、限定された種類のパーティショニングをサポートしています。BigTableや他のDKVSシステムほど柔軟性がなく、数百に簡単に分割できません。のサーバーにすることはできませんが、実際にはそれがあなたが探しているもののようには聞こえません。データのインデックス作成と正規化を行い、強力なハードウェア(特に、余裕がある場合はSSD)でデータベースを実行し、2、3、または5つの物理ディスクに分割する限り、数十億のレコード数を処理するのに非常に優れています。必要。

上記の基準を満たしている場合、企業環境で作業していて、適切なハードウェアとデータベースの最適化に費やすお金がある場合は、今のところSQLServerを使用します。ペニーをつまんでいて、これをローエンドのAmazon EC2クラウドコンピューティングハードウェアで実行する必要がある場合は、代わりにCassandraまたはVoldemortを選択することをお勧めします(.NETで動作するようになると仮定します)。


11

数十億の行セットサイズで作業する人はほとんどいません。スタックオーバーフローでこのようなリクエストが表示されることがほとんどですが、データは報告されているサイズに近いものではありません。

ダウンタイムがないと仮定すると、360億、1か月あたり30億、つまり1日あたり約1億、1時間あたり416万、1分あたり約7万行、1秒あたり11,000行が、12か月間持続的にシステムに流入します。

これらの数字は長いマージンで不可能ではありません。私はより大きなシステムを実行しましたが、それが実際に意味する量であることを再確認したいと思います。実際にこの量を持っているアプリはほとんどありません。

保存/取得に関して、あなたが言及していない非常に重要な側面は、古いデータのエージングです-削除は無料ではありません。

通常のテクノロジではパーティション化が行われていますが、GUIDベースのルックアップ/取得では、12か月全体で一致するすべての値を取得する必要があると仮定すると、パフォーマンスが低下します。GUID列にクラスター化インデックスを配置すると、関連付けられたデータが読み取り/書き込み用にクラスター化されますが、それらの量と挿入速度では、断片化が高すぎてサポートできず、フロアに落ちてしまいます。

また、これがOLTPタイプの応答速度を備えた深刻なアプリケーションである場合、つまり、インデックス作成のオーバーヘッドが非常に少ないと仮定すると、約2.7 TBのデータである場合、非常に適切なハードウェアバジェットが必要になることをお勧めします。

SQL Serverキャンプでは、データをシャーディングし、それに対して並列クエリを実行して大規模なデータマートに対して高速を提供するように設計された、新しい並列データウェアハウスエディション(マディソン)だけを確認する必要があります。


3
バイオインフォマティクスでは、10億行のデータセットは珍しいことではありません。ただし、フラットファイルから純粋にストリーミング方式で処理されることがよくあります。
エリックギャリソン

3
@Erik:ストリーム処理の場合(つまり、特定の条件を検出するだけで、後でクエリを実行するためにデータを保存する必要はありません)、StreamInsightのようなものはどのデータベースよりも優れていますmicrosoft.com/sqlserver/2008/en/us/r2 -complex-event.aspx
Remus Rusanu 2010年

2

「数十億のレコード(年間で約30億/月)の小さなデータ(約50〜75バイト)を保存できる必要があります。

唯一の要件は、同じGUIDを持つすべてのレコードの高速挿入と高速ルックアップ、および.netからデータストアにアクセスする機能です。」

これはSQLServerで可能であることが経験からわかります。これは、2009年の初めに行ったためです...そして、今日でも非常に高速に動作しています。

テーブルは256のパーティションに分割されました。これは、2005 SQLバージョンであることに注意してください...そして、あなたが言っていることを正確に実行しました。つまり、情報のビットをGUIDで格納し、GUIDですばやく取得します。

私が去ったとき、約20〜30億のレコードがあり、データ保持ポリシーがインスタンス化されようとしていたにもかかわらず、データの取得は依然として非常に良好でした(UIを通過する場合は1〜2秒、RDBMSの場合はそれ以下)。

つまり、簡単に言うと、GUID文字列から8番目の文字(つまり、中間のどこか)を取得し、SHA1がそれをハッシュして、小さなint(0-255)としてキャストし、適切なパーティションに格納して、取得時に同じ関数呼び出しを使用しました。データを戻します。

さらに情報が必要な場合は私にpingしてください...


2

次の記事では輸入と使用について説明し16十億のMicrosoft SQLでの行のテーブルを。 http://sqlmag.com/t-sql/adventures-big-data-how-import-16-billion-rows-single-table

記事から:

これが私の経験からのいくつかの蒸留されたヒントです:

  • クラスター化インデックスが定義されたテーブルにあるデータが多いほど、ソートされていないレコードをテーブルにインポートするのが遅くなります。ある時点で、それは実用的であるには遅すぎます。
  • テーブルを可能な限り小さいファイルにエクスポートする場合は、ネイティブ形式にします。これは、文字データよりもバイナリフィールドでよりコンパクトに表されるため、ほとんどが数値列を含むテーブルで最適に機能します。すべてのデータが英数字の場合、ネイティブ形式でエクスポートしてもあまりメリットはありません。数値フィールドにnullを許可しないと、データがさらに圧縮される可能性があります。フィールドをNULL可能にすることを許可すると、フィールドのバイナリ表現には、続くデータのバイト数を示す1バイトのプレフィックスが含まれます。
  • BCPカウンター変数は4バイト整数であるため、2,147,483,647レコードを超えるBCPを使用することはできません。MSDNまたはインターネットでこれへの参照を見つけることができませんでした。テーブル
    が2,147,483,647を超えるレコードで構成されている場合は、テーブルをチャンクでエクスポートする
    か、独自のエクスポートルーチンを作成する必要があります。
  • 事前入力されたテーブルでクラスター化インデックスを定義すると、多くのディスク領域が必要になります。私のテストでは、ログが
    完了する前に元のテーブルサイズの10倍に爆発しました。
  • BULK INSERTステートメントを使用して多数のレコードをインポートする場合は、BATCHSIZEパラメーターを含めて、一度
    にコミットするレコードの数を指定します。このパラメーターを含めない場合
    、ファイル全体が単一のトランザクションとしてインポートされます。
    ため、多くのログスペースが必要になります。
  • クラスター化インデックスを使用してデータをテーブルに取り込む最も速い方法は、最初にデータを事前に並べ替えることです。次に、BULKINSERT
    ステートメントとORDERパラメーターを使用してインポートできます。

1

見落とされているように見える珍しい事実があります。

基本的に、1日に3,000万行を挿入した後、同じGUID(おそらく20行)ですべての行をフェッチする必要があり、すべてを取り戻すことが合理的に確実です。

20列のみが必要なため、GUIDの非クラスター化インデックスは問題なく機能します。パーティション間でデータを分散させるために、別の列にクラスター化することができます。

データ挿入に関して質問があります:どのように挿入されますか?

  • これは特定のスケジュール(1分あたり、1時間あたりなど)での一括挿入ですか?
  • このデータはどのソースから取得されていますか(フラットファイル、OLTPなど)?

方程式の片側を理解するために、これらに答える必要があると思います。


1

AmazonRedshiftは素晴らしいサービスです。質問が2010年に最初に投稿されたときには利用できませんでしたが、2017年には主要なプレーヤーになりました。これはPostgresからフォークされた列ベースのデータベースであるため、標準のSQLおよびPostgresコネクタライブラリで動作します。

レポートの目的、特に集計に最適です。単一のテーブルからのデータは、Amazonのクラウド内の異なるサーバーに保存され、定義されたテーブルdistkeysによって分散されるため、分散CPUパワーに依存します。

そのため、SELECT、特に集約されたSELECTは非常に高速です。大きなデータの読み込みは、Amazon S3csvファイルからCOPYコマンドを使用して実行することをお勧めします。欠点は、DELETEとUPDATEが通常よりも遅いことですが、それが、Redshiftが主に多国籍データベースではなく、より多くのデータウェアハウスプラットフォームにある理由です。


0

CassandraまたはHBaseを使用してみることができますが、ユースケースに従って列ファミリーを設計する方法を読む必要があります。Cassandraは独自のクエリ言語を提供しますが、データに直接アクセスするにはHBaseのJavaAPIを使用する必要があります。Hbaseを使用する必要がある場合は、オープンソースプロジェクトであるMap-RのApacheDrillを使用してデータをクエリすることをお勧めします。ドリルのクエリ言語はSQL準拠です(ドリルのキーワードはSQLと同じ意味です)。


0

年間のレコード数が多いと、最終的にはスペースが不足します。2 ^ 64ファイルをサポートし、より小さなボックスを使用するxfsのようなファイルシステムストレージを使用してみませんか。いかに派手な人々が手に入れたいか、またはデータベースSQL NoSQLを使用してシステムを取得するために費やす金額に関係なく、これらの多くのレコードは通常、電力会社や気象観測所/環境省のような小規模な管理を行うプロバイダーによって作成されます。全国のステーション。圧力、温度、風速、湿度などを保存するようなことをしていて、GUIDが場所である場合でも、データを年/月/日/時間で割ることができます。ハードドライブごとに4年間のデータを保存するとします。次に、ミラー付きの小さなNasで実行して、読み取り速度を向上させ、複数のマウントポイントを設定できます。それが作成された年に基づいています。あなたは単に検索のためのウェブインターフェースを作ることができますそれで場所を捨てる1 / 2001/06/01/温度と場所1/2002/06/01 // Temperatureは、その2年間(24時間* 2)の夏の初日の1時間ごとの気温の内容のみをダンプします。これに対して、数十億のレコードと場合によっては数百万が費やされたデータベースを検索します。物事の簡単な見方..神のいる世界の15億のウェブサイトは、それぞれが何ページあるかを知っています。代わりに、彼らは電力料金を持っています...数百万台のがらくたコンピュータ。そしてカフェインの索引付け...将来性のある..さらに追加し続けます。そして、SQLから実行するインデックス作成が理にかなっている場合は、天気や統計などの固定されたタスクのためのスーパーコンピューターを構築して、技術者がシステムを自慢できるようにしますxtbをx秒でクランチします...お金の無駄になる可能性がありますどこかで過ごした。


-2

レコードをプレーンなバイナリファイル(GUIDごとに1つのファイル)に保存しても、それより速くなることはありません。


5
これがうまく機能することを本当に期待していますか?
ChaosPandion 2010年

3
ええ、ファイルシステム上に数十億のファイルを作成すると、一部のファイルシステムに壊滅的な打撃を与える可能性があります。私はこのようなことをするのを間違えましたが、たった100万で、それらのフォルダーの1つへのシェルを開こうとしてシステムをほとんどダウンさせました。また、GUIDに基づいて検索しない限り、クエリメカニズムはどのように機能するはずですか?
ロブグッドウィン2010年

予想される一意のGUIDの数がわからないと、これがどのように実行されるかを推測するのは困難です:)しかし、単純なファイルに書き込むよりも簡単なことはありません。そして、GUIDによるルックアップを伴う高速挿入が唯一の要件でした。
トーマスKjørnes

それは機能しますが、フォルダごとのファイル数を制限する必要があります。nファイルごとに新しいフォルダを生成する必要があります。guidのサブストリングをフォルダー名として使用できます。
TTT 2010年

1
はい、多くのファイルシステムのiノードの数には制限があります。RedHatのデフォルトのファイルシステムでその制限に達したのを覚えています。制限は約1,000,000ファイル程度でした。
ディーンヒラー2013年

-3

MongoDBを使用し、GUIDをシャーディングキーとして使用できます。つまり、データを複数のマシンに分散できますが、シャーディングキーで選択するため、選択するデータは1台のマシンにのみ存在します。

MongoDbでのシャーディングは、まだ本番環境に対応していません。

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