メールアドレスを主キーとして使用しますか?


234

自動インクリメントの数値と比較した場合、電子メールアドレスはプライマリの候補として不適切ですか?

私たちのウェブアプリケーションは、システムで一意である電子メールアドレスを必要とします。そこで、メールアドレスを主キーにしようと考えました。ただし、私の同僚は、文字列の比較は整数の比較よりも遅くなることを示唆しています。

電子メールを主キーとして使用しないのは正当な理由ですか?

使用していPostgreSQLます。


5
「プライマリ」とはどういう意味ですか?電子メールアドレスを一意にする必要がある場合、それはキーであり、一意の制約が必要です。たとえば、パフォーマンスが低いシステムを最適化するなど、実際的な理由がない限り、「プライマリ」になることを「プロモート」するかどうかは任意です。
onedaywhen

7
データベースに一意のメールアドレスを強制する場合は、一意のインデックスを持つ列を作成しますが、それを主キーとして使用しないでください。
James Westgate

104
@robert誰かが自分のメールアドレスを変更したい場合はどうなりますか?すべての外部キーも変更しますか?
systempuntoout 2010

3
@onedaywhen-ほとんど違いはありませんが、主キーはデフォルトでクラスター化されますが、一意のインデックスはクラスター化されません。デフォルトの単一レコードルックアップキーとなる主キーを定義する必要があります。一意のインデックスは、通常のインデックスに対して列の一意性を強制するだけです
James Westgate

3
@James Westgate:参考までに、PostgreSQLには自動クラスタリングなどはありません。PRIMARY KEYは、すべてのフィールドがNULLではないUNIQUE INDEXとまったく同じようにディスクに実装されます。
Matthew Wood

回答:


283

文字列の比較は、intの比較よりも時間がかかります。ただし、電子メールアドレスを使用してデータベースからユーザーを取得するだけの場合は問題ありません。複数の結合を持つ複雑なクエリがある場合は重要です。

ユーザーに関する情報を複数のテーブルに格納する場合、usersテーブルへの外部キーは電子メールアドレスになります。つまり、電子メールアドレスを複数回保存することになります。


11
@Sjoerd:問題はメールアドレスが複数回保存されることではありませんが、それは明らかに非効率的ですが、今日のハードドライブ容量を気にしている人です。ほとんどの企業には、これが問題になるgoogle-scaleがありません。問題は、メールアドレスはプライマリキーであり、外部キーとして参照されるため、後で変更できないことです。
Stefan Steiger、2015

@StefanSteiger誰がハードドライブの容量について何か言いましたか?保存したものはすべてRAMのスペースを占有します。
ジョナサンアレン

誰かが不思議に思った場合、私がしたように、GUIDキーは電子メールキーと同等だと思います。
tofutim 2016

178

また、メールはユニークな分野を作るのに悪い選択であることを指摘します。メールアドレスを共有する人々や小規模ビジネスさえあります。また、電話番号と同様に、メールは再利用できます。Jsmith@somecompany.comは、1年後のJohn Smithと2年後のJulia Smithに簡単に所属できます。

メールのもう1つの問題は、メールが頻繁に変更されることです。それをキーとして他のテーブルに参加している場合は、他のテーブルも更新する必要があります。これは、クライアント企業全体が電子メールを変更したときにパフォーマンスに大きな影響を与える可能性があります(これは私が経験したことです)。


47
カスケード更新の問題について言及するための+1。これが、友達が代理キーのみを使用できるようにする理由です;-)。
sleske

10
ああ、私はこの言葉がまったく好きではありません...代理キーも問題の原因になる可能性があります。はい、アプリケーションはビジネスや整合性のルールの変更に対してより堅牢になりますが、情報が少し簡単に失われる可能性があり、レコードのIDが不明確になります。だから私はここでの経験則をお勧めしません ...
Unreason

12
@onedaywhenと@jay、あなたがそれがユニークであるはずだと思っているからといって、それをユニークにしないでください。そして、はい、夫婦は別の顧客かもしれません。これまでに遭遇したことがないからといって、それが起こらないという意味ではありません。私はそれに遭遇しました、そして、それはあなたがそれがそうであるはずであるかどうかに関係なく、電子メールがユニークであると考えられることを決して許されるべきでない理由で起こります。これは本質的に間違っているため、あなたが押し戻す一種の要件です。
HLGEM 2010

15
@HLGEM:私は無限の議論に入りたいとは思わないが、提案されたキーは、コンテキストを知らずに仮説に基づいて一意ではないとは言えない。たとえば、電話会社の観点から見ると、電話番号は定義により顧客を一意に識別します。はい、「でも、その番号に電話をかけると答える可能性のある2人または3人の人がいたらどうなるでしょうか」と言うことができます。しかし、これは無関係です。電話会社の観点からは、定義上、これは1人の顧客です。(続く...)
Jay

14
(続き)同様に、電子メール通信に主に関係するシステム(おそらくメッセージディスパッチシステム、または通知転送システム)を構築している場合、定義により、電子メールアドレスはユーザーを一意に識別する可能性があります。複数の人がその電子メールアドレスを共有している場合、それは無関係です。これらは単一のメッセージ宛先であるため、単一のユーザーです。「ユーザー」と「お客様」は「個人」と同義語である必要はありません。
ジェイ

99

主キーは一意かつ一定である必要があります

メールアドレスは季節ごとに変わります。ルックアップの2次キーとしては便利ですが、1次キーとしては不適切です。


17
優れたキーの特性は、安定している必要があるが、必ずしも不変ではないということです。
10

5
@onedaywhen:うん!それ以外の場合、SQLはカスケード更新をサポートするのはなぜですか?
ビルカーウィン2010

18
選択肢がある場合は、定数/不変のキーを使用してください。今後の作業が減ります。SQLがカスケード更新をサポートしているからといって、それが常に良いアイデアであるとは限りません!
スティーブンA.ロウ

7
@Vincent Malgrat:「カスケード更新... dbの正規化にブレーキをかける」-正規化の概念を誤解していると思われます!
10

5
@Vincent Malgrat:正規化の概念を本当に誤解していることを確認していただきありがとうございます。「複数の行で同じ情報を繰り返すべきではありません」-「情報」と言うつもりでしたか?!複合キーには通常、複数の行で繰り返される値が含まれます。外部キーの場合、値は「繰り返される」のではなく参照され、大きな違いがあります。2つの値(たとえば、「はい」と「いいえ」)を持つ単一列ドメインは、3つ以上の行がある場合、参照テーブルの複数の行に同じ値を持ちます。これは本当に基本的なものです!
10

64

メールアドレスを主キーとして使用することの欠点:

  1. 結合を行うと遅くなります。

  2. ポストされた外部キーを持つ他のレコードは、より大きな値になり、より多くのディスク領域を占有します。(今日のディスク容量のコストを考えると、レコードの読み取りに時間がかかる範囲を除いて、これはおそらく些細な問題です。#1を参照してください。)

  3. メールアドレスが変更される可能性があり、これを外部キーとして使用するすべてのレコードが強制的に更新されます。メールアドレスはそれほど頻繁には変更されないため、パフォーマンスの問題はおそらく軽微です。より大きな問題は、それを提供することを確認する必要があることです。コードを書く必要がある場合、これはより多くの作業であり、バグの可能性をもたらします。データベースエンジンが「更新時のカスケード」をサポートしている場合、それは小さな問題です。

メールアドレスを主キーとして使用する利点:

  1. 一部の結合を完全に排除できる場合があります。「マスターレコード」から必要なのが電子メールアドレスだけである場合、抽象整数キーを使用して、それを取得するために結合を行う必要があります。キーがメールアドレスの場合、すでに持っているので参加は不要です。これが役立つかどうかは、この状況が発生する頻度に依存します。

  2. アドホッククエリを実行すると、参照されているマスターレコードを人間が簡単に確認できます。これは、データの問題を追跡するときに大きな助けになります。

  3. いずれにしても、メールアドレスにインデックスが必要になることはほぼ確実です。これを主キーにすると1つのインデックスが削除され、更新するインデックスが2つではなく1つになるため、挿入のパフォーマンスが向上します。

私の控えめな意見では、どちらの方法でもスラムダンクではありません。私は実際のキーが利用可能である場合、自然なキーを使用することを好む傾向があります。なぜなら、それらは扱いが簡単であり、ほとんどの場合、デメリットはあまり問題にならない傾向があるからです。


@Conrad:ただし、ON UPDATE CASCADEをサポートするエンジンがある場合、それはPITAではないと指摘します。その時点ではコード的には問題ではありません。唯一の本当の問題は、更新がどれほど広範囲に及ぶか、そしてどれだけ広いかが鍵です。メールアドレスは少々多いかもしれませんが、2文字の国コードのPKのCASCADE UPDATEは大したことではありません。
マシューウッド

5
@マシュー私見それはまだピタ。たとえば、国テーブルを設計したときに、それを参照するテーブルが2つしかなく、大したことはなかったと仮定しますが、時間の経過とともに、それぞれ数十万のレコードを持つ20個のテーブルになります。参照ありのものとないものがあります。これにより、単一のロジックの書き込みが数万回の書き込みになり、テーブルが追加されたときに誰かが参照を忘れたため、すべてのテーブルに書き込まれるわけではありません。これは、2文字の国コードテーブルで私に起こったこととまったく同じです。
コンラッドFrix

@Wood&Conrad:最悪のケースは、組み込みのDBサポートがない場合です。次に、投稿された参照を含むすべてのテーブルについて、そのためのコードを記述する必要があります。これは、バグが侵入するための苦痛と扉です。カスケードを使用すると、各テーブルに句を1つずつ追加することを忘れないでください。大したこと。
ジェイ

2
利点1と3は時期尚早の最適化であり、利点2は非常に小さな利点であり、適切なクエリツールによって完全に克服されます。
Ash

4
@Ash:これは、「optimizatin」と「時期尚早の最適化」の違いです。しかし、大丈夫、同じ理由で、私が誰かが言及したのを見たすべての欠点は時期尚早な最適化です。それで、あなたはどこにあなたを置きますか?#2については、アドホッククエリを実行しようとすると、追加の結合を入力するのが大変です。多くの場合、レコードには複数の外部キーがあるため、包括的なデータを取得するには複数の結合が必要になる場合があります。「きちんとしたクエリツール」とは、何も言わずに見たいデータを見つけ出し、魔法のように結合してくれるツールの場合、それがどのように機能するかを知りたいと思います。
ジェイ

12

それはかなり悪いです。一部の電子メールプロバイダーが廃業したとします。その後、ユーザーは自分の電子メールを変更する必要があります。電子メールを主キーとして使用している場合、ユーザーのすべての外部キーはその電子メールを複製するため、変更するのはかなり困難です...

...そして私はパフォーマンスの考慮についてさえ話し始めていません。


メールアドレスを変更すると、重複がどのように発生しますか?ユーザーAが自分のメールアドレスを変更してから、ユーザーBが自分のメールをユーザーAの古い値と同じに変更しない限り、更新は順番に行われません。リモートで可能だと思います。
ジェイ

2
外部キー参照には、定義により、参照する行の主キーの値が含まれます。つまり、主キーの値を複製します。(したがって、値の変更によって複製が引き起こされることはありません。しかし、この複製とそれを強制する制約のために、変更はより困難です)。
メリトン

5
「一部の電子メールプロバイダーが倒産したと仮定します」という行の+1。
レディ

これは問題ありません。この問題を解決するために、外部キーのカスケードが存在します。ユーザーが電子メールを変更すると、その変更は外部キーとして使用されているすべてのテーブルにカスケードされます。
Rafa 2013

1
@rafa、あなたがカスケード更新を使用し、プロバイダー全体が廃業するか、その名前を変更した場合(Yahoo.comがHooYa.comになる)、これがカスケードされている間、データベースはすべてのユーザーに対して数時間およびおそらく数日間ロックされますシステムを通じて。これは非常に有効な問題である(そして、あなたが任意のデータを大量に持っていると、キーが変更される可能性がある場合は、更新をカスケード接続し使用することが悪い考えである理由。)
HLGEM

12

これがセットアップの問題であるかどうかはわかりませんが、RDBMSによっては、列の値で大文字と小文字が区別される場合があります。PostgreSQLのドキュメントでは、次のように述べています。言い換えると、電子メールを主キーとするテーブルでの検索に対するユーザー入力を受け入れ、ユーザーが「John@Doe.com」を提供した場合、「john@doe.com」は見つかりません。


7
この関連で、John @ Doe.comとjohn@Doe.comが同じメールボックスであるか、異なるメールボックスである可能性があることを言及する価値があります。通知する方法はありません。ローカルパーツが大文字かどうかは、仕様に記載されていません。敏感。
10

これは、電子メールアドレスを主キーとして使用する必要があるかどうかではなく、一意性の強制に関するより一般的な問題です。同じ問題がどちらの方法でも発生します。+1は依然として非常に有用なポイントであるため

11

電子メールアドレスが非公開と見なされる可能性のある問題について誰も言及していないようです。電子メールアドレスが主キーである場合、プロファイルページのURLは次のようになり..../Users/my@email.comます。ユーザーのメールアドレスを公開したくない場合はどうしますか?ユーザーを特定する他の方法を見つける必要があります。URLをにするために、おそらく一意の整数値を使用します..../Users/1。その後、結局のところ、一意の整数値が返されます。


9

論理レベル、電子メールは、自然キーです。で、物理レベル、リレーショナルデータベースを使用している与えられた、自然なキーが主キーとしてうまく適合しません。その理由は、主に他の人が言及したパフォーマンスの問題です。

そのため、デザインを変更することができます。自然キーが代替キー(UNIQUE、NOT NULL)になり、代理キー/人工/技術キーを主キーとして使用します。これは、場合によっては自動インクリメントになります。

systempuntooutは尋ねました、

誰かが自分のメールアドレスを変更したい場合はどうなりますか?すべての外部キーも変更しますか?

それがカスケードの目的です。

数値サロゲートキーを主キーとして使用するもう1つの理由は、プラットフォームでのインデックスの機能に関連しています。たとえば、MySQLのInnoDBでは、テーブル内のすべてのインデックスの前に主キーが付加されているため、PKを可能な限り小さくする必要があります(速度とサイズのため)。これに関連して、InnoDBは主キーが順番に格納されている場合はより高速であり、文字列はそこで役立ちません。

代替キーとして文字列を使用するときに考慮すべきもう1つのことは、必要な実際の文字列のハッシュを使用すると、一部の文字の大文字と小文字などをスキップして、より高速になる可能性があることです。(私が実際にここに着陸したのは、私が言ったことを確認するための参照を探している最中ですが、まだ探しています...)


5

はい、ユーザーは自分の電子メールアドレスを更新する必要があるため、これは不適切な主キーです。


1
カスケードがあるのでこれは問題ではないことを指摘したいと思います
マルハル2016

4

はい、代わりに整数を使用することをお勧めします。メール列を一意の制約として設定することもできます。

このような:

CREATE TABLE myTable(
    id integer primary key,
    email text UNIQUE
);

8
なぜ「より良い」のですか?理由や情報源はありますか?
シェード

20
詳しく説明していただけますか?
Sjoerd

3

整数の主キーの方が優れているもう1つの理由は、別の表で電子メールアドレスを参照する場合です。アドレス自体が主キーの場合、別のテーブルでは、それをキーとして使用する必要があります。したがって、メールアドレスを複数回保存します。


3

私はpostgresにあまり詳しくありません。主キーは大きなトピックです。私はこのサイト(stackoverflow.com)でいくつかの素晴らしい質問と回答を見てきました。

数値の主キーを使用し、Eメール列にUNIQUE INDEXを使用すると、パフォーマンスが向上すると思います。電子メールは長さが異なる傾向があり、主キーインデックスには適切でない場合があります。

ここここを読んください。


3

個人的には、データベースの設計時に主キーの情報を使用していません。これは、後で情報を変更する必要がある可能性が非常に高いためです。主キーを提供する唯一の理由は、ほとんどのSQL操作をクライアント側から実行するのが便利であり、そのための私の選択は常に自動インクリメントの整数型でした。


2

同僚は正しい:主キーに自動インクリメント整数を使用します。

アプリケーションレベルでメールの一意性を実装するか、メールアドレスの列を一意としてマークし、その列にインデックスを追加します。

フィールドを一意として追加すると、そのテーブルに挿入する場合にのみ文字列の比較にコストがかかります。結合や外部キー制約チェックを実行する場合はそうではありません。

もちろん、データベースレベルでアプリケーションに制約を追加すると、アプリケーションの柔軟性が失われる可能性があることに注意する必要があります。アプリケーションでフィールドを一意または空にする必要がないという理由だけで、フィールドを「一意」または「非null」にする前に、常に十分な検討を行ってください。


1
「アプリケーションが要件xを必要とするからといって、要件xを実装する前に常に十分な検討を行ってください。」-私がかなり前に読んだ最悪のアドバイス。
10

私はあなたの「議論」に確信が持てません-実際の生活では、いくつかの重要なデータ(例えば、電話番号)がすぐに利用できない状況がしばしばあります。そのようなフィールドがデータベースでNOT NULLとしてマークされている場合、ユーザーはデータを空のままにする代わりに、ダミーフィールド(123など)でデータを汚染する必要があります。アプリケーションに制約を処理させるほうが実用的です(この場合、アプリは空のフィールドにアクションアイテムとしてフラグを立てることができます)。
jrharshath

5
「nullではない」フィールドの定義は慎重に行う必要があることに同意します。「常にお客様の電話番号が必要」などの要件は慎重に検討する必要があります。現在電話番号がわからなくても、顧客レコードを作成し、戻って後で取得することが望ましくない場合がありますか?ただし、「このフィールドは一意である必要があります」は別のカテゴリです。「2人の従業員が同じ社会保障番号を持っているのは大丈夫です。後でわかります」とは思えません。データをどのように整えますか?
ジェイ

1
オオカミになる:私はかつて自分の電話番号を持っていない女性を知っていました。だったらどうしようか?
David Thornley、

@DavidThornleyあなたはもっとうまくやるべきか、あるいはおそらく友好的な態度を採用すべきだと思います。
フィリップシフ2017年

2

GUIDを主キーとして使用します。これにより、INSERTを実行するときにプログラムからGUIDを生成でき、サーバーから応答を取得して主キーが何であるかを確認する必要がありません。また、テーブルとデータベース全体で一意となり、いつかテーブルを切り捨てて自動インクリメントが1にリセットされた場合に何が起こるかを心配する必要はありません。


2
パフォーマンスについてほとんど気にしない限り、GUIDを使用してください。スケーリングが必要なシステムを構築している場合は、No-No#1です
Micah


3
本当のマイクロソフト・クール・エイド・ドリンクのファッションで言った!
Gary Chambers、

2

私はこれが少し遅いエントリであることを知っていますが、メールアカウントを放棄し、サービスプロバイダーが別の人が使用できるようにアドレスを回復したことを付け加えておきます。

@HLGEMが指摘したように、「Jsmith@somecompany.comは、1年後にはJohn Smithに、2年後にはJulia Smithに簡単に所属できます。」この場合、ジョンスミスがあなたのサービスを希望する場合、彼のメールアドレスの使用を拒否するか、ジュリアスミスに関するすべてのレコードを削除する必要があります。

レコードを削除する必要があり、そのレコードが地域の法律に応じて事業の財務履歴に関連している場合は、お湯に浸かることがあります。

したがって、メールアドレス、ナンバープレートなどのデータを主キーとして使用することは決してありません。それらがどのように一意であるかは関係なく、それらは制御不能であり、対処する時間がないかもしれない興味深い課題を提供できるからです。


2

該当するデータ規制の法律を検討する必要がある場合があります。電子メールは個人情報であり、たとえばユーザーがEU市民である場合、GDPRの下でユーザーは記録から情報を削除するように指示できます(これは、拠点とする国に関係なく適用されることに注意してください)。

参照整合性や監査などの履歴上の理由でデータベース自体にレコード自体を保持する必要がある場合は、代理キーを使用すると、すべての個人データフィールドをNULLにすることができます。個人データが主キーである場合、これは明らかに簡単ではありません


1

整数の主キーを使用してパフォーマンスを向上させることができます。


1

整数の主キーを使用する必要があります。email-columnを一意にする必要がある場合は、その列にunique-indexを設定しないでください。


1

主キーとしてint以外の値がある場合、大きなデータでは挿入と取得が非常に遅くなります。


1
いいえ、挿入は遅くなります。生成された主キーと電子メールアドレスの2つの一意のインデックスが必要だからです。
a_horse_with_no_name 2013年

1

主キーには静的属性を選択する必要があります。電子メールアドレスは静的ではなく、複数の候補者で共有できるため、それらを主キーとして使用することはお勧めできません。さらに、電子メールアドレスは通常、特定の長さの文字列であり、使用したい一意のID [len(email_address)> len(unique_id)]よりも長い場合があるため、より多くのスペースが必要で、最悪の場合、外部キーとして複数回保存されます。その結果、パフォーマンスが低下します。


0

テーブルによって異なります。テーブルの行が電子メールアドレスを表す場合、電子メールが最適なIDです。そうでない場合は、メールは適切なIDではありません。


0

電子メールを一意にする必要があるだけの場合は、その列で一意のインデックスを作成できます。


0

メールは一意のインデックス候補としては適していますが、主キーには適していません。主キーの場合、連絡先の電子メールアドレスなどを変更することはできません。結合クエリも遅くなると思います。


0

電子メールアドレスを主キーとして使用せず、電子メールを一意のままにしますが、主キーとして使用せず、ユーザーIDまたはユーザー名を主キーとして使用します

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