web-dev-qa-db-ja.com

Mysql:192兆レコードの操作...(はい、192兆)

これが質問です...

192兆件のレコードを考えると、私の考慮​​事項は何ですか?

私の主な関心事は速度です。

これがテーブルです...

    CREATE TABLE `ref` (
  `id` INTEGER(13) AUTO_INCREMENT DEFAULT NOT NULL,
  `rel_id` INTEGER(13) NOT NULL,
  `p1` INTEGER(13) NOT NULL,
  `p2` INTEGER(13) DEFAULT NULL,
  `p3` INTEGER(13) DEFAULT NULL,
  `s` INTEGER(13) NOT NULL,
  `p4` INTEGER(13) DEFAULT NULL,
  `p5` INTEGER(13) DEFAULT NULL,
  `p6` INTEGER(13) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY (`s`),
  KEY (`rel_id`),
  KEY (`p3`),
  KEY (`p4`)
    );

これがクエリです...

SELECT id, s FROM ref WHERE red_id="$rel_id" AND p3="$p3" AND p4="$p4"

SELECT rel_id, p1, p2, p3, p4, p5, p6 FROM ref WHERE id="$id"

INSERT INTO rel (rel_id, p1, p2, p3, s, p4, p5, p6)
VALUES ("$rel_id", "$p1", "$p2", "$p3", "$s", "$p4", "$p5", "$p6")

ここにいくつかの注意事項があります...

  • SELECTはINSERTよりも頻繁に実行されます。ただし、一度に数百のレコードを追加したい場合があります。
  • ロードに関しては、何時間も何もないため、一度に数千のクエリが実行される可能性があります。
  • これ以上正規化できるとは思わない(組み合わせのp値が必要)
  • データベースは全体として非常にリレーショナルです。
  • これはこれまでで最大のテーブルになります(次の最大は約900kです)

更新(2010年8月11日)

興味深いことに、私は2番目のオプションを与えられました...

192兆の代わりに2.6 * 10 ^ 16(15個のゼロ、つまり26兆)を保存できます...

しかし、この2番目のオプションでは、1つのbigint(18)をインデックスとしてテーブルに格納するだけで済みます。それだけです-1列だけです。したがって、私は値の存在をチェックしているだけです。ときどきレコードを追加し、削除しないでください。

ですから、単純に数値を格納するためのmysqlよりも優れた解決策があるはずだと思います...

この2番目のオプションを考えると、それを取るか、最初のものに固執するべきですか...

[[edit]行われたいくつかのテストのニュースを受け取りました-この設定で1億行が0.0004秒でクエリを返します[/ edit]

39
Sarah

pQdの7PBの推定値 は妥当なようですが、これはRDBMSの大量のデータです。 MySQLは言うまでもなく、共有ディスクシステムで7PBをしている人の話を聞いたことがあるかどうかはわかりません。共有ディスクシステムを使用してこの量のデータをクエリすると、処理速度が著しく低下します。最速のSANハードウェアは、大規模なストリーミングクエリ用に調整された場合でも、20GB /秒で最大になります。このスペックのSANハードウェアを使用できる場合は、 MySQLよりもジョブに適したもの。

実際、私は、この仕様のディスクサブシステムの予算はあるが、より優れたDBMSプラットフォームの予算はないというシナリオを想像するのに苦労しています。 600GBのディスク(現在市場に出ている最大の15Kの「エンタープライズ」ドライブ)を使用しても、7PBを格納するのに12,000の物理ディスクドライブのようなものが必要です。 SATAディスクは安価です(2TBのディスクの場合、数の約1/3が必要になります)が、かなり低速です。

A SAN EMCやHitachiなどの主要ベンダーのこの仕様の場合、数百万ドルに上ります。前回、SAN主要ベンダーの機器を使用して、IBM DS8000でのスペースの転送コストは、1万ポンド/ TBを超えていましたが、コントローラーの資本金は含まれていません。

この大量のデータには、TeradataやNetezzaのようなシェアードナッシングシステムが本当に必要です。 MySQLデータベースのシャーディングは機能する可能性がありますが、専用のVLDBプラットフォームを構築することをお勧めします。シェアードナッシングシステムでは、ノードではるかに安価な直接接続ディスクを使用することもできます。1つの可能性として、SunのX4550(サンパー)プラットフォームを見てください。

また、パフォーマンス要件についても考慮する必要があります。

  • クエリの許容実行時間はどれくらいですか?
  • どのくらいの頻度でデータセットをクエリしますか?
  • クエリの大部分はインデックスを使用して解決できますか(つまり、データの1%未満-のようなわずかな部分を調べます)、それとも全テーブルスキャンを実行する必要がありますか?
  • データはどのくらいの速さでデータベースにロードされますか?
  • クエリには最新のデータが必要ですか、または定期的に更新されるレポートテーブルを使用できますか?

要するに、MySQLに対する最も強力な主張は、可能であれば、7PBのデータに対してまともなクエリパフォーマンスを得るためにバックフリップを行うことです。この大量のデータは本当に無シェア領域にあなたを入れ、それをかなり速くクエリする何かを作ります、そしておそらく最初から無シェア操作のために設計されたプラットフォームが必要でしょう。ディスクだけで、妥当なDBMSプラットフォームのコストを削減できます。

注:運用データベースとレポートデータベースを分割する場合、必ずしも両方に同じDBMSプラットフォームを使用する必要はありません。同じ7PBテーブルから高速の挿入と1秒未満のレポートを取得することは、少なくとも技術的な課題になります。

レポートに多少のレイテンシがあってもかまわないというコメントから、キャプチャシステムとレポートシステムを個別に検討することができ、運用上のキャプチャシステムに7PBのデータをすべて保持する必要がない場合があります。 Oracleなどの運用プラットフォーム(MySQLはInnoDBを使用してこれを実行できます)でデータキャプチャを検討します(ここでも、ロットがない限り、ディスクのコストだけでDBMSのコストが小さくなりますのユーザー)および Teradata、Sybase IQ、RedBrick、Netezza のようなVLDBプラットフォーム(注:独自のハードウェア) )または Greenplum レポート用

それを破る。このサイズで1つの大きなインスタンスを持つことは自殺です。考えられるバックアップリストア、テーブルスペースの破損、新しい列の追加、またはその他の「ハウスキーピング」プロセスについて考えてみてください。これらすべてをこの規模で妥当な時間内に実行することは不可能です。

エンベロープ計算の単純な裏側-64ビットIDを除くすべての列に32ビット整数を想定。インデックスが含まれていません:

8 * 4B + 8B =行あたり40B [これは非常に楽観的です]

それぞれ192兆行40Bで約7 PB

全体を再考し、迅速なレポートのために情報を要約し、誰かがより詳細に掘り下げる必要がある場合は、指定された時間間隔で圧縮レコードを保存できます。

回答する質問:

  • システムがクラッシュ/再起動した場合の許容ダウンタイムは何ですか?
  • 計画的なメンテナンスのためにバックアップを回復したり、サーバーを本番環境から外したりする必要がある場合のアクセス可能なダウンタイム.
  • どのくらいの頻度で、どこでバックアップしたいですか?

ランダムリンク-挿入速度:

16
pQd

Percona を呼び出します。 「Go」を渡さないでください。 200ドルは集めないでください。

8

編集:実際には、それが整数の範囲内の場所Xの「レコード」の存在であるかどうかだけの場合、データストアを削除してビットマップを使用することができます...つまり、100 TBディスク容量(パフォーマンスとバックアップ用にビットマップの10コピーがあるため)、および128GBのRAMサーバーごとに実行した場合、高解像度の最上位ブロックグループに適合できます。 26 XのビットXのディスクをヒットする前に最初のチェックを実行するためのメモリ内のインデックス。

オプション#2を選びます。

それぞれ64 TB(32 2 TBドライブ)の375台のマシン(実際には障害の場合は400台のマシン)は、それぞれ2 TBのZVOLにレコードをマップします。次に、1つまたは複数のインデックスサーバーで、Judy配列またはcritbit配列または単純なビットマップに、26兆の1のロケーションにレコードを追加したかどうかのマッピングを保存します。インデックスは50〜100 TBであり、64 GB未満に収まるアドレスの特定の64kブロックにRAMまた、特定の "近隣"が空であるかどうかにかかわらず、初期レベルのチェックを迅速に行うことができます。

次に、そのレコードを読み取るには、まずインデックスを調べて、検索するレコードがあるかどうかを確認します。ある場合は、単純なインデックス計算に基づいて、その2TBブロブ内のそのマシン/レコードロケーション#(Z)のマシン#(X)/ ZOL#(Y)に移動します。単一レコードのルックアップは非常に高速であり、データストアの一部を別のdbにロードしてテストし(実際の作業にデータストアを使用している間)、パフォーマンステストを実行して、データベース全体をサポートできるかどうかを確認できます。そのようにデータストアを使用するだけです。

ZOLは、他のファイルシステムのスパースファイルと考えることができるZFSのものであるため、同様のことが当てはまります。または、ディスク上の特定のバイト数にインデックスを付けることもできますが、ディスクごとに使用されるバイト数をすべてのディスクで機能するレベル(つまり、2 TBディスクあたり1.75 TB)でキャップしないと、ディスクのサイズが異なる場合、これはトリッキーになります。または、固定サイズのメタデバイスなどを作成します。

2
Ann E. Mouse

あなたがしたいすべてがそれらがセットにあるかどうかを確認することである場合、数十億の数値を保存するよりも、別の方法があるかもしれません。 ブルームフィルター は、複数の方法でハッシュすることによる確率的方法です。また、誤検知は可能ですが、誤検知はできません。 (それで、それは数がセットにあると言うかもしれません-そして間違っているかもしれませんが、それが本当にあったとしても、そこにないとは言いません)。保存するアイテムの膨大な数の問題も残っていますが、少なくとも、作業データセットのサイズが多少小さくなる可能性があります。

2
Alister Bulman

クレイジーな(たとえばmysqltunerを使用して)のようにDBパラメーターを調整して、SELECTをできるだけ人間の目でキャッシュするようにする以外に、数百のレコードを挿入してSTART TRANSACTION/CoMMIT(InnoDBを想定)を調査することもできます。行ごとにロックするオーバーヘッドがあり、挿入時間を大幅に短縮します。 MyISAMとInnoDBの両方としてテーブルを作成し、テストを実行して、キャッシュが厳しくなったときにどれが本当に高速であるかを確認します。

http://www.mysqlperformanceblog.com/2007/01/08/innodb-vs-myisam-vs-falcon-benchmarks-part-1/

テスト中、並行スレッドの数も上下に変えて、RAMキャッシュのチューニング専用にサーバーに費やす余裕がある程度)のスイートスポットを見つける必要があります。数学ではより多くのスレッドをサポートできますが、スレッド数が多すぎると、DB自体のパフォーマンスが低下する可能性があります。

また、MyISAMやInnoDB file-per-tableを使用する場合は、/ var/lib/mysqlに別のファイルシステムマウントポイントを作成して、より小さなブロックサイズに調整し、fsタイプのパラメーター(つまりext3 /)を調整することを検討できます。 ext4/resiserfsを使用すると、ジャーナルにdata = writebackを使用し、I/O速度のためにファイルシステムのアクセス時間の更新を無効にすることができます。

1
user15590

2番目のオプションの場合、実際に配置される可能性のある数はいくつですか?

1000に1つしか存在しない場合、または10K、100Kなどの場合、使用済み(または未使用)の数値の範囲を保存すると、何兆ものエントリを節約できます。例:( 'free'、0,100000)、( 'taken'、100000,100003)、( 'free'、100004,584234)-必要に応じて行を2つまたは3つの行に分割し、最初の数値にインデックスを付ける、 x <= {needle}を検索して、検索された数値を含む範囲が使用されているか、空いているかを確認します。

両方のステータスを必要としない場合もあります。最も可能性の低いステータスを保存します。

0
Alister Bulman