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


39

ここに質問があります...

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番目のオプションが与えられた場合、それを使用するか、最初のオプションを使用するか...

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


7
このためにMySQLをどのように使用しますか?誰かがそうするための確固たる議論を提供するなら、あなたは異なるdbmsに切り替えると確信できますか?
WheresAlice

3
10 ^ 12または10 ^ 18のような兆?
andol

15
192兆件のレコードでは、ディスカッションフォーラムではなく、MySQLコミッターに質問できる予算が必要です。
レムスルサヌ

5
この大規模なデータベース(そして明らかにまともな予算)で、大規模なDBを簡単に処理できることが証明されているoracleまたはsql sererソリューションを選択してみませんか?
ジムB

5
これを実装するときは、必ず最新の状態にしてください。きっと興味があります。あなたはまたのためにそれを書きたいかもしれませんhighscalability.com
トム・オコナー

回答:


30

7PBのpQdの推定は妥当であるように思われ、それはRDBMSにとって大量のデータです。MySQLはもちろんのこと、誰かが共有ディスクシステムで7PBを実行していることを聞いたことはありません。共有ディスクシステムでこのデータ量を照会すると、使用できないほど遅くなります。大規模なストリーミングクエリ用に調整された場合でも、最速のSANハードウェアは20GB /秒で最大になります。この仕様のSANハードウェアを購入できる場合は、MySQLよりもジョブに適したものを使用できます。

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

EMCや日立のような主要ベンダーのこの仕様のSANは、数百万ドルに達するでしょう。前回大手ベンダーのSAN機器を使用したとき、IBM DS8000のスペースの転送コストは£10,000で、コントローラーの資本控除は含まれていませんでした。

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

また、パフォーマンス要件を考慮する必要があります。

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

要するに、MySQLに対する最も強力な論点は、可能な場合は7PBのデータで適切なクエリパフォーマンスを得るためにバックフリップを行うということです。この大量のデータは、シェアードナッシング領域に実際に入れて、合理的に迅速にクエリを実行するものを作成します。おそらく、最初からシェアードナッシング操作用に設計されたプラットフォームが必要になるでしょう。ディスクだけで、妥当なDBMSプラットフォームのコストを大幅に削減できます。

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

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


1
@ConcernedOfTunbridgeW-彼らはいつでもこの方法で行くことができます:blog.backblaze.com/2009/09/01/…-SANよりもはるかに楽しい、必要なのは〜120-130 4Uボックスだけですが...ビジネス」は幸せになります....
pQd

基本的には予算内のSun Thumperであり、シェアードナッシングシステムのノードのオプションの実例です。私はこれのための他のオプションも見たことがあると確信していますが、どこで考えることはできません。問題は、ハードウェアではなく、データベースプラットフォームです。
ConcernedOfTunbridgeWells

ただし、熱心なオブザーバーは、このような種類の直接接続ベースのボックスは、SANに基づくものよりもTBあたりはるかに安価であることに気付くでしょう。 。
ConcernedOfTunbridgeWells

@ConcernedOfTunbridgeWellsを使用すると、これらのすべてのクエリ/メンテナンスなどを複数の[そうでない場合は電力を消費する]ボックスで並行して実行できます。
pQd

1
@ConcernedOfTunbridgeWells-質問に答えるには...可能であれば、1秒以内に戻るために約500のクエリが必要です。これは1日に数百回しか行いません。ただし、クエリを実行するときは、テーブル全体をスキャンする必要があります。また、INSERTの優先度はSELECTの優先度よりも低いため、瞬時に近い場所にある必要はありません。「新しい」データがデータベースに入るのを数時間待つことができます。
サラ

16

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

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

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

192兆行40Bごとにほぼ7 PBが得られます

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

答える質問:

  • システムがクラッシュしたり再起動したりした場合の許容可能なダウンタイムはどれくらいですか?
  • バックアップを復旧したり、計画的なメンテナンスのためにサーバーを運用環境から引き出したりする必要がある場合に利用できるダウンタイム。
  • バックアップの頻度と場所

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


私は同意します-7PBはかなり重いです。私はそれを再考し、より軽い解決策を見つけたいと思っていますが、pフィールドの特定の組み合わせの存在(または存在しない)を見つける必要があります。テーブルを分割することは私の心を越えました-それはより賢明ですが、それはちょうど私が各テーブルを順番にクエリを持っていることを意味します。興味深いことに、ここに分割することをお勧めするテーブルはいくつありますか?
サラ

5
@Sarah-テーブルに分割するだけでなく、マシンにも分割することをお勧めします。クエリを並行して実行してパフォーマンスを向上させることができます[小規模で実行します]。ファイルシステムの破損や、サーバーの再起動後の定期的な検査についてはどうですか?特定の組み合わせを見つけることの意味がわかりません...多分単純なキーバリューストアが役立つでしょうか?テーブルサイズ-数十GB以下 単一サーバー上のデータ-数TB以下。stackoverflow.com/questions/654594を見て、はるかに小さなスケールで予想される頭痛の種を把握してください。innodb_file_per_tableを使う
PQD


2

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


面白いように思えますが、偽陰性と一緒に暮らすことはできますが、偽陽性はありません。)
サラ

2

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

あなたが取るなら、私はオプション#2に行きます:

それぞれ64TB(32個の2TBドライブ)を備えた375台のマシン(障害に対して現実的には400台のマシン)は、それぞれ2TBのZVOLにレコードをマップします。次に、1つまたは複数のインデックスサーバーで、Judy配列またはcritbit配列、または単なるビットマップに保存します。26のQuadrillionの場所の1つにレコードを追加した場合のマッピング。インデックスは50〜100 TBであり、64 GB未満のRAMに収まり、高速レベルの初期チェックを提供する特定の64kアドレスブロックに書き込まれたレコードがある場合は、第2レベルのインデックスを提示することもできます。特定の「近所」が空かどうか。

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

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


こんにちはサラ-まだこれに取り組んでいるかどうかはわかりませんが、助けが必要な場合は、100TBのマシンであなたのアイデアをプロトタイプし、(主要な米国のデータセンターで)ホストし、必要に応じて400〜500台のマシン。ところで、SFのCNETで働いたことはありますか?

1

SELECTを人為的にできるだけ多くキャッシュしようとするために、DBパラメーターをクレイジーに調整する(mysqltunerを使用する)以外に、数百のレコードを挿入する際にSTART TRANSACTION / CoMMIT(InnoDBを想定)を調査することをお勧めします行ごとにオーバーヘッドをロックし、挿入時間を大幅に短縮します。また、テーブルをMyISAMとInnoDBの両方として作成し、そのテストを実行して、キャッシュが強化された後、どれが本当に速いかを確認します。MyISAMが読み取りに対して常に高速になるとは限りません。

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に別のファイルシステムマウントポイントを作成することを調査できます。 ext4 / resiserfsでは、ジャーナルにdata = writebackを使用し、I / O速度のためにファイルシステムのアクセス時間の更新を無効にすることができます。


1
myisamは、トランザクションの要件により問題になっていないようです。
pQd

0

2番目のオプションでは、実際に配置される可能性のある数字の数は?

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

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

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