2009-06-29 8 views
9

多くのテキストを格納するデータベースを計画しています。 (ブログ記事、ニュース記事など)データベースには、タイトル、コンテンツ(最大50K文字)、日付、リンク、言語フィールドが必要です。同じコンテンツは1つのリンクでは発生しません。古いコンテンツ(30日より古いなど)は削除されます。PostgreSQL:大きなデータベースに主キーを定義する

ここで問題は主キーです。私はちょうど自動増分(SERIALタイプ)フィールドを設定してプライマリキーとして使用することができます。しかし、それはフィールドが目的を果たすのではなく、主キーとなるため、ディスクスペースの浪費と馬鹿に思えます。 (そしてフィールドは最終的に不足する可能性がありますか?)また、常に新しいパフォーマンスの問題があります。挿入された新しい行の内容を重複してチェックする必要があります。だから私が思い付いたプライマリキーのもう一つの解決策は、コンテンツ+リンク値のsha256ハッシュを計算し、それを新しい 'ハッシュ'カラムに入れてそれをプライマリキーとして使うことです。 1つの石で2羽の鳥。もちろん、その問題はハッシュの衝突です。それは大きな脅威ですか?

私はPostgreSQLについての経験はほとんどありません。DBMSの経験はほとんどありませんので、高速道路上のカタツムリのパフォーマンス特性(恐ろしい比較)を持つデータベースを作成する前に、もう一度ご意見ください。

大きなデータベースでの経験があれば、ここで手伝ってください。私の状況では、64文字の文字列をプライマリキーフィールドとして設定するのが良いアイデアですか? (私は印象の下だから、一般的に、これは回避される)

答えて

9

ただ、かなり大きな差で勝ったBIGSERIAL、むしろ、中大型DB(200ギガバイト+)のために、この正確なテストをしました。生成するのが速く、結合が速く、コードが少なく、フットプリントが小さくなりました。 postgresがそれを格納する方法のため、bigintは通常のintに比べて無視できます。 bigintのオーバーフローを心配する前に、コンテンツからストレージスペースを使い果たしてしまいます。計算されたハッシュ対bigint - サロゲートbigintを終わらせたこと。

+0

は、あなたのテストでは、「他のパフォーマンスの問題を:それぞれの新しい行の内容を挿入する必要の[原文]重複をチェックする」が含まれていましたか? – onedaywhen

2

ヒント:

  • 64ビットの主キーの整数のディスクストレージは関係なく、あなたが持っているどのくらいの内容無視できません。
  • あなたはSHA256を決して衝突させず、一意のIDとして使用することは悪い考えではありません。

ハッシュ法の素晴らしい点の1つは、新しい主キーを生成するための単一のシーケンスソースがないことです。これは、将来のスケーリングのためにデータベースを何らかの方法(地理的分布など)でセグメント化する必要がある場合、またはシーケンスを生成する単一ポイント障害を心配する必要がない場合に役立ちます。

コーディングの観点から、単一の主キーを持つことは、将来追加する可能性のある追加のテーブルに参加するために不可欠なことです。私は非常に1つを使用することをお勧めします。あなたの提案されたアプローチのいずれかに利点がありますが、自動インクリメント/シーケンス値が時々スケーラビリティの問題を引き起こす可能性があるため、ハッシュ方法が好ましい方法かもしれません。

+1

SHA256を主キーとして使用している場合、それを変更する必要はありませんか?コンテンツ+リンクの値が変わるとどうなりますか? –

+0

Harvey、良い点ですが、行のコンテンツ値を変更する場合は、新しいコンテンツ+リンクのalredyのハッシュが存在するかどうかを確認します。そうなら、変更は起こりません。 – KRTac

+0

コンテンツが変更された場合は、新しいレコードを作成しますか? –

1

ハッシュは主キーのための悪い考えです。彼らはインサートがテーブル内で無作為な順序で終わるようにします。そして、それは事を再配分しなければならないので非常にコストがかかる(Postgresは他人のやり方に実際には当てはまらないが)。私は、連続したプライマリキーを提案しています。これは細かいタイムスタンプ/タイムスタンプで、連続した番号が続き、石で2羽の鳥を殺すことができ、ハッシュコードを含む2番目のユニークなインデックスです。主キーを小さい(64ビット以下)列にしておきたいことに注意してください。

http://en.wikipedia.org/wiki/Birthday_attack#The_mathematicsの表を参照すると、衝突しないと確信できます。

真空を忘れないでください。

3

主キーの整数が不足する前に、非常に多くのレコードを保持する必要があります。

64文字列の主キーよりも結合の方が高速です。また、クエリを書く人々が対処する方がはるかに簡単です。

衝突が今まで可能であるならば、あなたは主キーとしてハッシュを使用することはできません。主キーは定義によって一意になるようにする必要があります。

私は別の企業や政府機関のための本番データベースの数百人を見てきましたし、ない1は、ハッシュ主キーを使用していました。理由があると思う?

しかし、フィールドは目的を果たしずにプライマリキーになるため、ディスクスペースが浪費しているようです。

サロゲートプライマリキーはプライマリキー以外は常に意味がありませんので、私はあなたの反対が何であるか分かりません。

+0

私はテーブルにたくさんの行があることを計画しています。古い行は削除されますが、フィールドは自動的に行数をインクリメントし続けます。シリアルフィールドが2147483647に達すると、それ以上の行をテーブルに入れることはできません。 – KRTac

+1

32ビット符号付き整数を参照しています。 64ビット符号付き整数の場合、最大値は9,223,372,036,854,775,807です。あなたはそれを使い果たしてしまうのではないかと思う。 –

+1

それは速く、ハッシュ、エバンそれは64ビットのintですね? – KRTac

3

私はサロゲートキーを使用することを選択します。アプリケーションのビジネスデータの一部ではないキー。 1レコードにつき50キロバイトまでのテキストを処理する場合、追加の64ビット整数の追加スペース要件はごくわずかです。このキーを他のテーブルの外部キーとして使用し始めると、より小さいスペースを実際に使用します。レコードに格納されたデータのハッシュを使用して

主キーのための非常に悪い候補である、ハッシュがこれまでに基づいているデータを変更する必要があります。プライマリキーも変更して、他のテーブルからこのテーブルへのリレーションシップがあれば、その場で更新されます。

PS。同様の質問がここで尋ねられ、回答しましたbefore。ここで

は、トピックについて他の素敵な書き込みアップだ: http://www.agiledata.org/essays/keys.html

+0

大きなアドバイス、私はそれにほとんど同意します。しかし、私が以前に述べたように、surogat鍵が2147483647に達するとどうなりますか?私はbigserialを使うことができましたが、そのパフォーマンスはどうですか? – KRTac

+0

この文脈(ブログ記事とニュース記事を保存する)では、2^31の項目に到達する可能性は非常に高いと思われます。あなたは前もって計画し、それが安全なプレーとBIGSERIAL使用したい場合はそうであっても、私はもパフォーマンスヒットが特にPKとしてCHAR(32)を使用する場合と比較して、最小限のだろうと思います。 –

1

通常の32ビット整数を主キーとして使用します。私はすぐにその数を超えるとは思わない:-) Wikipedia全体には約3,500万件の記事がある... 1日1000件の記事を書いた場合、整数型の最大値に達するのに6000年かかるだろう。

関連する問題