web-dev-qa-db-ja.com

大きなテキストにインデックスを付けるための最適なハッシュ手法

Erwin Brandstetter ありがたいことに 自分から救われた 長いテキストの列に一意のインデックスを作成しようとしたとき。

挿入率の上限は、年間数百億行です。

私の実装では、ハッシュはデータベースから離れる必要はありませんが、ハッシュデータは頻繁に存在するために外部データと比較する必要があります。

これらの目的のための最適化の限られた経験では、ハッシュの最適なデータ型はbyteaであると思います。もちろん、もう1つの方法は、はるかに長い16進文字列です。

byteaがこれらのハッシュに最適なデータ型であることは正しいですか?

byteaが最適ではない場合、何ですか?

私の意図はどのように実装されるべきですか?

説明

大きなテキストが一意であることを確認できるように、Erwin Brandstetterの推奨に従ってテキストのハッシュを使用しています。特に文字列と比較した場合、生のバイナリデータが常に最もパフォーマンスが高いことは、私の限られた理解です。

ハッシュは、一意性違反を回避するために存在を比較する必要があるだけなので、ハッシュはデータベースを離れる必要はありません。 libpqxxの信じられないほどの設計のため、準備されたステートメントを介してデータを単純に入力し、(decode(md5($1::text), 'hex'))で変換できるように見えます。 libpqxx 3.1を介したbytea挿入に慣れてきたら、c ++に移動します。

この実装では、システムを壊すことなくデータを再構築して適合させることができるため、衝突は許容されます。

最大スループットに問題なく到達した場合、それに対応するための経済的リソースが利用可能になると予想されます。したがって、主な関心事は常にパフォーマンスです。Postgresの機能と、パーティション化されたテーブルがこれらの量の行を処理する機能についての私の理解が正確であれば、それは長い間、仕事に適したツールとなるでしょう。幸いなことに、数秒より古いデータは決して変更されず、Postgresパーティションテーブルがそのようなデータからミンチ肉を作成できることは私の理解です。そうでない場合、これはそれらの良い問題の1つになります。

6
user32234

byteaはハッシュの保存に最適です。

PostgreSQLのバイナリワイヤプロトコル(libpqによってサポートされ、一部はPgJDBCによってサポートされている)を使用して転送しない限り、それはとにかくデータベースから16進文字列として転送されます。

最良の結果を得るには、byteaとして保存し、クライアントアプリケーションでバイナリ結果を要求するPQexecParams呼び出しを使用するようにします。

読み直しに関しては、これは混乱を招きます:

私の実装では、ハッシュはデータベースを離れる必要はありませんが、ハッシュデータは頻繁に存在するために外部データと比較する必要があります

ハッシュは比較のために転送されず、元のハッシュされていないテキストデータは転送されるということですか?その場合、バイナリプロトコルはテキスト形式のデータにはメリットがないため、上記は関係ありません。

また、「数百億」の行はたくさんあります。 PostgreSQLは28バイトで行ごとのオーバーヘッドが非常に大きいため、多くのスペースを失うことになります。特に、インデックスのオーバーヘッドも考慮に入れてください。 PostgreSQLはこの仕事に適したツールですか?

最後に、行数が多くなると、ハッシュ衝突の領域に入ります。 可能性あり-2つの異なる文字列が同じハッシュを持っている可能性はありますが、間違った一意の違反が報告されるかどうかを気にしますか?それが問題である場合、ハッシュの一意のBツリーインデックスは、おそらくその仕事に適したツールではありません。

5
Craig Ringer