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