自動インクリメントの数値と比較した場合、電子メールアドレスはプライマリの候補として不適切ですか?
私たちのウェブアプリケーションは、システムで一意である電子メールアドレスを必要とします。そこで、メールアドレスを主キーにしようと考えました。ただし、私の同僚は、文字列の比較は整数の比較よりも遅くなることを示唆しています。
電子メールを主キーとして使用しないのは正当な理由ですか?
使用していPostgreSQL
ます。
自動インクリメントの数値と比較した場合、電子メールアドレスはプライマリの候補として不適切ですか?
私たちのウェブアプリケーションは、システムで一意である電子メールアドレスを必要とします。そこで、メールアドレスを主キーにしようと考えました。ただし、私の同僚は、文字列の比較は整数の比較よりも遅くなることを示唆しています。
電子メールを主キーとして使用しないのは正当な理由ですか?
使用していPostgreSQL
ます。
回答:
文字列の比較は、intの比較よりも時間がかかります。ただし、電子メールアドレスを使用してデータベースからユーザーを取得するだけの場合は問題ありません。複数の結合を持つ複雑なクエリがある場合は重要です。
ユーザーに関する情報を複数のテーブルに格納する場合、usersテーブルへの外部キーは電子メールアドレスになります。つまり、電子メールアドレスを複数回保存することになります。
また、メールはユニークな分野を作るのに悪い選択であることを指摘します。メールアドレスを共有する人々や小規模ビジネスさえあります。また、電話番号と同様に、メールは再利用できます。Jsmith@somecompany.comは、1年後のJohn Smithと2年後のJulia Smithに簡単に所属できます。
メールのもう1つの問題は、メールが頻繁に変更されることです。それをキーとして他のテーブルに参加している場合は、他のテーブルも更新する必要があります。これは、クライアント企業全体が電子メールを変更したときにパフォーマンスに大きな影響を与える可能性があります(これは私が経験したことです)。
主キーは一意かつ一定である必要があります
メールアドレスは季節ごとに変わります。ルックアップの2次キーとしては便利ですが、1次キーとしては不適切です。
メールアドレスを主キーとして使用することの欠点:
結合を行うと遅くなります。
ポストされた外部キーを持つ他のレコードは、より大きな値になり、より多くのディスク領域を占有します。(今日のディスク容量のコストを考えると、レコードの読み取りに時間がかかる範囲を除いて、これはおそらく些細な問題です。#1を参照してください。)
メールアドレスが変更される可能性があり、これを外部キーとして使用するすべてのレコードが強制的に更新されます。メールアドレスはそれほど頻繁には変更されないため、パフォーマンスの問題はおそらく軽微です。より大きな問題は、それを提供することを確認する必要があることです。コードを書く必要がある場合、これはより多くの作業であり、バグの可能性をもたらします。データベースエンジンが「更新時のカスケード」をサポートしている場合、それは小さな問題です。
メールアドレスを主キーとして使用する利点:
一部の結合を完全に排除できる場合があります。「マスターレコード」から必要なのが電子メールアドレスだけである場合、抽象整数キーを使用して、それを取得するために結合を行う必要があります。キーがメールアドレスの場合、すでに持っているので参加は不要です。これが役立つかどうかは、この状況が発生する頻度に依存します。
アドホッククエリを実行すると、参照されているマスターレコードを人間が簡単に確認できます。これは、データの問題を追跡するときに大きな助けになります。
いずれにしても、メールアドレスにインデックスが必要になることはほぼ確実です。これを主キーにすると1つのインデックスが削除され、更新するインデックスが2つではなく1つになるため、挿入のパフォーマンスが向上します。
私の控えめな意見では、どちらの方法でもスラムダンクではありません。私は実際のキーが利用可能である場合、自然なキーを使用することを好む傾向があります。なぜなら、それらは扱いが簡単であり、ほとんどの場合、デメリットはあまり問題にならない傾向があるからです。
それはかなり悪いです。一部の電子メールプロバイダーが廃業したとします。その後、ユーザーは自分の電子メールを変更する必要があります。電子メールを主キーとして使用している場合、ユーザーのすべての外部キーはその電子メールを複製するため、変更するのはかなり困難です...
...そして私はパフォーマンスの考慮についてさえ話し始めていません。
これがセットアップの問題であるかどうかはわかりませんが、RDBMSによっては、列の値で大文字と小文字が区別される場合があります。PostgreSQLのドキュメントでは、次のように述べています。言い換えると、電子メールを主キーとするテーブルでの検索に対するユーザー入力を受け入れ、ユーザーが「John@Doe.com」を提供した場合、「john@doe.com」は見つかりません。
電子メールアドレスが非公開と見なされる可能性のある問題について誰も言及していないようです。電子メールアドレスが主キーである場合、プロファイルページのURLは次のようになり..../Users/my@email.com
ます。ユーザーのメールアドレスを公開したくない場合はどうしますか?ユーザーを特定する他の方法を見つける必要があります。URLをにするために、おそらく一意の整数値を使用します..../Users/1
。その後、結局のところ、一意の整数値が返されます。
で論理レベル、電子メールは、自然キーです。で、物理レベル、リレーショナルデータベースを使用している与えられた、自然なキーが主キーとしてうまく適合しません。その理由は、主に他の人が言及したパフォーマンスの問題です。
そのため、デザインを変更することができます。自然キーが代替キー(UNIQUE、NOT NULL)になり、代理キー/人工/技術キーを主キーとして使用します。これは、場合によっては自動インクリメントになります。
systempuntooutは尋ねました、
誰かが自分のメールアドレスを変更したい場合はどうなりますか?すべての外部キーも変更しますか?
それがカスケードの目的です。
数値サロゲートキーを主キーとして使用するもう1つの理由は、プラットフォームでのインデックスの機能に関連しています。たとえば、MySQLのInnoDBでは、テーブル内のすべてのインデックスの前に主キーが付加されているため、PKを可能な限り小さくする必要があります(速度とサイズのため)。これに関連して、InnoDBは主キーが順番に格納されている場合はより高速であり、文字列はそこで役立ちません。
代替キーとして文字列を使用するときに考慮すべきもう1つのことは、必要な実際の文字列のハッシュを使用すると、一部の文字の大文字と小文字などをスキップして、より高速になる可能性があることです。(私が実際にここに着陸したのは、私が言ったことを確認するための参照を探している最中ですが、まだ探しています...)
同僚は正しい:主キーに自動インクリメント整数を使用します。
アプリケーションレベルでメールの一意性を実装するか、メールアドレスの列を一意としてマークし、その列にインデックスを追加します。
フィールドを一意として追加すると、そのテーブルに挿入する場合にのみ文字列の比較にコストがかかります。結合や外部キー制約チェックを実行する場合はそうではありません。
もちろん、データベースレベルでアプリケーションに制約を追加すると、アプリケーションの柔軟性が失われる可能性があることに注意する必要があります。アプリケーションでフィールドを一意または空にする必要がないという理由だけで、フィールドを「一意」または「非null」にする前に、常に十分な検討を行ってください。
GUIDを主キーとして使用します。これにより、INSERTを実行するときにプログラムからGUIDを生成でき、サーバーから応答を取得して主キーが何であるかを確認する必要がありません。また、テーブルとデータベース全体で一意となり、いつかテーブルを切り捨てて自動インクリメントが1にリセットされた場合に何が起こるかを心配する必要はありません。
私はこれが少し遅いエントリであることを知っていますが、メールアカウントを放棄し、サービスプロバイダーが別の人が使用できるようにアドレスを回復したことを付け加えておきます。
@HLGEMが指摘したように、「Jsmith@somecompany.comは、1年後にはJohn Smithに、2年後にはJulia Smithに簡単に所属できます。」この場合、ジョンスミスがあなたのサービスを希望する場合、彼のメールアドレスの使用を拒否するか、ジュリアスミスに関するすべてのレコードを削除する必要があります。
レコードを削除する必要があり、そのレコードが地域の法律に応じて事業の財務履歴に関連している場合は、お湯に浸かることがあります。
したがって、メールアドレス、ナンバープレートなどのデータを主キーとして使用することは決してありません。それらがどのように一意であるかは関係なく、それらは制御不能であり、対処する時間がないかもしれない興味深い課題を提供できるからです。
該当するデータ規制の法律を検討する必要がある場合があります。電子メールは個人情報であり、たとえばユーザーがEU市民である場合、GDPRの下でユーザーは記録から情報を削除するように指示できます(これは、拠点とする国に関係なく適用されることに注意してください)。
参照整合性や監査などの履歴上の理由でデータベース自体にレコード自体を保持する必要がある場合は、代理キーを使用すると、すべての個人データフィールドをNULLにすることができます。個人データが主キーである場合、これは明らかに簡単ではありません
主キーとしてint以外の値がある場合、大きなデータでは挿入と取得が非常に遅くなります。
主キーには静的属性を選択する必要があります。電子メールアドレスは静的ではなく、複数の候補者で共有できるため、それらを主キーとして使用することはお勧めできません。さらに、電子メールアドレスは通常、特定の長さの文字列であり、使用したい一意のID [len(email_address)> len(unique_id)]よりも長い場合があるため、より多くのスペースが必要で、最悪の場合、外部キーとして複数回保存されます。その結果、パフォーマンスが低下します。