web-dev-qa-db-ja.com

データベース1:1の関係を使用することが理にかなっているときはありますか?

先日、正規化について考えていましたが、それは私に起こりました。データベースに1対1の関係があるべき時間を考えることはできません。

名前:SSN?それらを同じテーブルPersonID:AddressIDに入れますか?繰り返しますが、同じテーブル。

1:manyまたはmany:many(適切な中間テーブルを使用)の無数の例を思いつくことができますが、1:1は決してありません。

明らかな何かが欠けていますか?

154
Pulsehead

通常、1対1の関係は、何らかの理由でより大きなエンティティをパーティション分割したことを示します。多くの場合、これは物理スキーマのパフォーマンス上の理由によるものですが、データの大部分が同時に「不明」であることが予想される場合(この場合、1:0または1:1、ただしそれ以上)。

論理パーティションの例として、従業員に関するデータはありますが、ヘルスカバレッジを選択した場合にのみ、収集する必要があるデータのセットが大きくなります。ヘルスカバレッジに関する人口統計データを別のテーブルに保存して、セキュリティのパーティション分割を容易にし、保険に関係のないクエリでそのデータを持ち歩くことを回避します。

物理パーティションの例は、複数のサーバーでホストされている同じデータです。ヘルスカバレッジの人口統計データを別の状態(HRオフィスなど)に保持し、プライマリデータベースはリンクサーバーを介してのみリンクできます。機密データを他の場所に複製せずに、 (ここでは珍しいと仮定)それを必要とするクエリ。

物理パーティションは便利ですwheneverより大きなエンティティの一貫したサブセットを必要とするクエリがある場合。

154
Godeke

1つの理由は、データベースの効率です。 1:1の関係を使用すると、行/テーブルのロック中に影響を受けるフィールドを分割できます。テーブルAに大量の更新があり、テーブルbに大量の読み取りがある(または別のアプリケーションからの大量の更新がある)場合、テーブルAのロックはテーブルBで行われていることに影響しません。

他の人は良い点を持ち出します。アプリケーションなどがシステムにどのようにアクセスしているかによって、セキュリティも正当な理由になります。私は別のアプローチを取る傾向がありますが、特定のデータへのアクセスを制限する簡単な方法です。ピンチで特定のテーブルへのアクセスを拒否するのは本当に簡単です。

それに関する私のブログエントリ。

120
kemiller2002

まばら。データ関係は技術的には1:1ですが、対応する行はすべての行に存在する必要はありません。したがって、2,000万の行があり、それらの0.5%にのみ存在する値のセットがある場合、それらの列をまばらに入力できるテーブルにプッシュすると、スペースの節約は非常に大きくなります。

41
chaos

上位の回答のほとんどは、1:1関係の非常に有用なデータベースチューニングと最適化の理由を提供しますが、1:1関係が自然に発生する「実際の」例にのみ焦点を当てたいと思います。

これらの例のほとんどのデータベース実装の1つの重要な特性に注意してください。1:1の関係に関する履歴情報は保持されません。つまり、これらの関係は任意の時点で1:1です。データベース設計者がリレーションシップ参加者の経時的な変更を記録する場合、リレーションシップは1:MまたはM:Mになります。彼らは1:1の性質を失います。それを理解した上で、ここに行きます:

  • 「Is-A」またはスーパータイプ/サブタイプまたは継承/分類関係:このカテゴリは、あるエンティティが別のエンティティの特定のタイプである場合です。たとえば、すべての従業員に適用される属性を持つEmployeeエンティティがあり、その従業員タイプに固有の属性を持つ特定のタイプの従業員を示すさまざまなエンティティがあります。医師、会計士、パイロットなど。この設計では、多くの従業員が特定のサブタイプの特化された属性を持たないため、複数のヌルが回避されます。このカテゴリの他の例として、スーパータイプとしての製品、サブタイプとしてのManufacturingProductおよびMaintenanceSupplyがあります。スーパータイプとしての動物とサブタイプとしての犬と猫。など。オブジェクト指向の継承階層をリレーショナルデータベース(オブジェクトリレーショナルモデルなど)にマップしようとするときはいつでも、これがそのようなシナリオを表す一種の関係であることに注意してください。

  • "ボス"関係(マネージャー、チェアパーソン、プレジデントなど)。組織単位には上司を1人だけ含めることができ、1人は1つの組織単位の上司にすることができます。これらのルールが適用される場合、部署のマネージャー、会社のCEOなど、1対1の関係があります。「ボス」の関係は、人だけに適用されるわけではありません。たとえば、会社の本社として店舗が1つしかない場合や、国の首都が1つの都市のみである場合にも、同様の関係が発生します。

  • いくつかの種類の希少なリソース割り当て、例えば1人の従業員には一度に1つの社用車しか割り当てられません(たとえば、トラック運転手ごとにトラック1台、タクシー運転手ごとにタクシー1台など)。同僚が最近この例を与えてくれました。

  • 結婚(少なくとも一夫多妻制が違法である司法管轄区では):1人の人が一度に結婚できるのは他の1人だけです。この例は、会社が従業員間の結婚を記録するときの1:1の単項関係の例としてこれを使用した教科書から得ました。

  • 予約のマッチング:一意の予約が行われ、2つの別個のエンティティとして満たされる場合。たとえば、レンタカーシステムでは、あるエンティティで予約を記録し、次に別のエンティティで実際のレンタルを記録する場合があります。そのような状況は1つのエンティティとして設計することもできますが、すべての予約が満たされるわけではなく、すべてのレンタルが予約を必要とするわけではないため、エンティティを分離するのが理にかなっています。

履歴情報が記録されていない場合にのみ、これらのほとんどが1:1の関係であるという先ほどの警告を繰り返します。そのため、従業員が組織内で役割を変更した場合、マネージャーが別の部門の責任を負う場合、従業員が車両を再割り当てされた場合、誰かが未亡人で再婚した場合、関係の参加者は変更できます。データベースにこれらの1:1関係に関する以前の履歴が保存されていない場合、それらは正当な1:1関係のままです。しかし、データベースが履歴情報(各関係の開始日と終了日を追加するなど)を記録する場合、それらはほとんどすべてM:M関係に変わります。

履歴メモには2つの顕著な例外があります。1つ目は、一部の関係が非常にまれに変更されるため、通常、履歴情報が保存されないことです。たとえば、ほとんどのIS-A関係(製品タイプなど)は不変です。つまり、変更することはできません。したがって、歴史的な記録ポイントは重要ではありません。これらは常に自然な1:1の関係として実装されます。第二に、予約とレンタルはそれぞれ独自の日付を持つ独立したイベントであるため、予約とレンタルの関係ストアの日付は別々になります。エンティティには独自の日付があり、1:1の関係自体に開始日があるため、履歴情報が保存されていても、これらは1:1の関係のままです。

24
Tripartio

あなたの質問は、あなたがそれを言葉にした方法のために、いくつかの方法で解釈されます。応答はこれを示しています。

現実の世界では、データ項目間に1対1の関係があることは間違いありません。それについての質問はありません。 「is a」関係は一般に1対1です。車は乗り物です。 1台の車は1台の車両です。 1台の車が1台の車になる場合があります。一部の車両はトラックであり、その場合、1台の車両は車ではありません。この解釈にはいくつかの答えがあります。

しかし、私はあなたが本当に求めているのは... 1:1の関係が存在するとき、テーブルを分割する必要があると思いますか?言い換えれば、まったく同じキーを含む2つのテーブルがあるはずです。実際には、私たちのほとんどは主キーのみを分析し、他の候補キーは分析しませんが、その質問は少し異なります。

1NF、2NF、および3NFの正規化ルールでは、テーブルを同じ主キーを持つ2つのテーブルに分解(分割)する必要はありません。 BCNF、4NF、または5NFにスキーマを配置しても、同じキーを持つ2つのテーブルが作成される可能性があるかどうかは、まだ解決していません。私の頭の上から、答えはノーだと思います。

6NFと呼ばれる正規化のレベルがあります。 6NFの正規化ルールは、同じ主キーを持つ2つのテーブルになることは間違いありません。 6NFには、NULLを完全に回避できるという5NFより優れた利点があります。これは、すべてではありませんが一部のデータベース設計者にとって重要です。私はスキーマを6NFに入れることを決して気にしませんでした。

6NFでは、欠落データは、一部の列にNULLがある行ではなく、省略された行で表すことができます。

テーブルを分割するための正規化以外の理由があります。テーブルを分割すると、パフォーマンスが向上する場合があります。一部のデータベースエンジンでは、実際にテーブルを分割するのではなく、パーティション化することで同じパフォーマンスの利点を得ることができます。これには、論理設計を理解しやすくし、データベースエンジンに速度を上げるために必要なツールを提供するという利点があります。

21
Walter Mitty

主にいくつかの理由で使用しています。 1つは、データの変更率の大きな違いです。一部のテーブルには、以前のバージョンのレコードを追跡する監査証跡がある場合があります.10列のうち5列の以前のバージョンを追跡するだけで、それらの5列を監査証跡メカニズムのある別のテーブルに分割する方が効率的です。また、書き込み専用のレコード(会計アプリなど)がある場合もあります。あなたが間違いを犯した場合は、ドルの金額またはアカウントを変更することはできません。間違ったレコードを調整するために対応するレコードを作成し、修正エントリを作成する必要があります。テーブルには、更新または削除できないという事実を強制する制約がありますが、そのオブジェクトには、順応性のあるいくつかの属性があります。それらは、変更の制限なしに別のテーブルに保持されます。私がこれを行う別の時は、医療記録アプリケーションです。いったんサインオフすると変更できない訪問に関連するデータと、サインオフ後に変更できる訪問に関連する他のデータがあります。その場合、データを分割し、ロックされたテーブルにトリガーをかけて、サインオフ時にロックされたテーブルへの更新を拒否しますが、医師はサインオフしません。

別のポスターは、1対1が正規化されていないことについてコメントしましたが、状況によっては、特にサブタイピングについては意見が異なります。従業員テーブルがあり、主キーがSSNであるとします(これは一例です。これが別のスレッドにとって適切なキーかどうかについての議論を保存しましょう)。従業員にはさまざまなタイプがあります。たとえば、一時的または永続的であり、永続的である場合は、オフィスの電話番号など、入力するフィールドがさらにあります。 3番目の正規形データベースでは、列はキー、つまり従業員のみに依存する必要がありますが、実際には従業員とタイプに依存するため、1:1の関係は完全に正常であり、この場合に望ましいです。また、通常は10個の列が入力されているが、特定のタイプに対してのみ20個の列が追加されている場合、過度にまばらなテーブルを防ぎます。

19
Shane Delmore

私が考えることができる最も一般的なシナリオは、BLOBがある場合です。大きな画像をデータベースに保存するとします(通常、画像を保存するのに最適な方法ではありませんが、制約があると便利な場合があります)。通常、非ブロブデータのルックアップを改善するために、ブロブを別のテーブルに配置する必要があります。

13

純粋な科学の面では、はい、それらは無意味です。

実際のデータベースでは、めったに使用されないフィールドを別のテーブルに保持しておくと便利な場合があります。このフィールドのみを使用してクエリを高速化します。ロックなどを避けるため.

9
Quassnoi

情報が多すぎる場合は、1-1の関係も必要です。テーブル内の各レコードにはレコードサイズの制限があります。レコードサイズが大きくなりすぎないように、テーブルが2つに分割される場合があります(メインテーブルで最もよく照会される情報を使用)。また、テーブルが狭い場合、データベースはクエリでより効率的です。

8
HLGEM

ビューを使用してフィールドへのアクセスを制限するのではなく、特定のユーザーのみがアクセスできる別のテーブルに制限されたフィールドを保持することが理にかなっています。

8
eleven81

また、継承を使用するOOモデルがあり、継承ツリーをDBに永続化する必要がある状況も考えられます。

たとえば、Animalを継承するBirdとFishのクラスがあります。 DBには、Animalクラスの共通フィールドを含む「Animal」テーブルを作成できます。Animalテーブルには、Birdテーブルと1対1の関係があり、Fishと1対1の関係があります表。

この場合、レコードが鳥を表す場合、Fish-dataを含むすべての列がNULLに設定されている、BirdおよびFish-propertiesを保持するための多くのnull許容列を含むAnimalテーブルは必要ありません。

代わりに、Birdsテーブルにレコードがあり、Animalテーブルのレコードと1対1の関係があります。

8

また、「実際の」データベースの変更よりも少ない(知覚される)リスクで既に実稼働しているテーブルを拡張する方法でもあります。従来のシステムで1:1の関係を確認することは、多くの場合、初期設計後にフィールドが追加されたことを示す良い指標です。

6
J.T. Grimes

SQLでは、2つのテーブル間に1:1の関係を強制することは不可能です(テーブルが読み取り専用でない限り)。最も実用的な目的では、SQLの「1:1」関係は実際には1:0 | 1を意味します。

参照制約で必須のカーディナリティをサポートできないことは、SQLの重大な制限の1つです。 「遅延可能」制約は、実際には制約が強制されない場合があるため、実際にはカウントされません。

5
nvogel

人気のあるORMの1つでデータを使用している場合、オブジェクト階層に一致するように、テーブルを複数のテーブルに分割することができます。

4
Jason Punyon

私が1:1の関係をするとき、それは完全に関係の理由ではなく、体系的な理由のためだということがわかりました。

たとえば、ユーザーの予約済みの側面を1つのテーブルに配置し、ユーザーのユーザーが編集可能なフィールドを別のテーブルに配置すると、これらのフィールドのアクセス許可に関するルールをはるかに簡単に記述できることがわかりました。

しかし、理論的には、1対1の関係は完全に考案されており、ほとんど現象です。ただし、論理的には、データベースを簡単に抽象化するプログラムと最適化が可能です。

4
DevelopingChris

ほとんどの場合、誰かが「まあ、なぜ1にならないのか」と尋ねられるまで、デザインは1に1であると考えられます。この一般的なシナリオを見越して、概念を互いに時期尚早に切り離します。人と住所はそれほど緊密に結びついていません。多くの人が複数のアドレスを持っています。等々...

通常、2つの別個のオブジェクトスペースは、一方または両方を乗算できることを意味します(x:many)。 2つのオブジェクトが真に真に1:1であり、哲学的にさえすれば、それはもっと関係になります。これら2つの「オブジェクト」は、実際には1つのオブジェクト全体の一部です。

4
Mark Canlas

特定のシナリオでのみ必要な拡張情報。プログラムがテーブル上でコンパイルされるレガシーアプリケーションおよびプログラミング言語(RPGなど)(テーブルが変更された場合、プログラムを再コンパイルする必要があります)。ファイルに沿ったタグは、テーブルのサイズを心配する必要がある場合にも役立ちます。

3
Ryan Guill

1:1の関係で見られる最大の理由は、データベース設計のスーパータイプサブタイプです。このモデルに基づいて、不動産MLSデータ構造を作成しました。 5つの異なるデータフィードがありました。住宅、商業、マルチファミリー、ホテルおよび土地。

5つの個別のデータフィードに共通のデータを含むプロパティと呼ばれるSuperTypeを作成しました。これにより、すべてのデータ型で非常に高速な「単純な」検索が可能になりました。

5つのデータフィードごとに一意のデータ要素を格納する5つの個別のサブタイプを作成します。各SuperTypeレコードには、適切なSubTypeレコードと1対1の関係がありました。

顧客が詳細な検索が必要な場合、PropertyResidentialなどのスーパーサブタイプを選択する必要がありました。

ほとんどの場合、論理的な構造というよりも物理的な構造です。物理デバイス間でI/Oを分割したり、アクセス頻度の低いデータや同じオブジェクトのその他の属性よりも安全に保つ必要があるデータの分離に関連する他のクエリ最適化を活用するために、テーブルを垂直にパーティション化するために一般的に使用されます(SSN、給与など)。

1-1の関係を規定する唯一の論理的な考慮事項は、特定の属性が一部のエンティティにのみ適用される場合です。ただし、ほとんどの場合、エンティティ抽出を通じてデータをモデル化するためのより良い/より正規化された方法があります。

2
JohnFx

私の意見では、1:1の関係はRDBMSのクラス継承をマップします。共通の属性、つまり部分クラスのステータスを含むテーブルAがあります。継承された各クラスステータスは、特殊な属性を含むAテーブルと1:1の関係を持つテーブルBでRDBMSにマッピングされます。表名Aには、「キャスト」機能を表す「タイプ」フィールドも含まれています。

バイ・マリオ

1
Mario

セキュリティの目的には不必要ですが、セキュリティチェックを実行するより良い方法があります。 1つのドアのみを開くことができるキーを作成すると想像してください。キーで他のドアを開くことができる場合は、アラームを鳴らしてください。本質的に、「CitizenTable」と「VotingTable」を持つことができます。投票表に保存されている候補者1に対する市民1の投票。市民1が投票表に再び表示された場合、彼らはアラームになるはずです。候補者フィールドを参照せず、投票テーブルと市民テーブルを参照しているため、これは1対1の関係です。

例:

 Citizen Table
 id = 1, citizen_name = "EvryBod"
 id = 2, citizen_name = "Lesly"
 id = 3, citizen_name = "Wasserman"

 Candidate Table
 id = 1, citizen_id = 1, candidate_name = "Bern Nie"
 id = 2, citizen_id = 2, candidate_name = "Bern Nie"
 id = 3, citizen_id = 3, candidate_name = "Hill Arry"

次に、投票表が次のように表示される場合:

 Voting Table
 id = 1, citizen_id = 1, candidate_name = "Bern Nie"
 id = 2, citizen_id = 2, candidate_name = "Bern Nie"
 id = 3, citizen_id = 3, candidate_name = "Hill Arry"
 id = 4, citizen_id = 3, candidate_name = "Hill Arry"
 id = 5, citizen_id = 3, candidate_name = "Hill Arry"

市民番号3は、ベルン・ニーをだましている嘘つきのズボンであると言えます。ほんの一例です。

0
Lesly Revenge

1:1の関係は、1:1になるものはすべて同じテーブルに保持されるため、正規化を行う場合にはあまり意味がありません。

しかし、現実の世界では、多くの場合異なっています。アプリケーションインターフェイスに合わせてデータを分割することもできます。

0
Eppz

パフォーマンスに大きなメリットがある場合は、1対1の関係テーブルを作成できます。めったに使用されないフィールドを別のテーブルに入れることができます。

0
kta

おそらく、データベースに何らかのタイプのオブジェクトがある場合。

テーブルT1で、1対1の関係を持つ列C1、C2、C3…があるとします。 OK、正規化された形式です。ここで、テーブルT2には、1対1の関係を持つ列C1、C2、C3、…(名前は異なる場合がありますが、タイプとロールは同じである)があるとします。 T1と同じ理由で、T2でも問題ありません。

ただし、この場合は、C1、C2、C3…、およびT1からT3、T2からT3の1対1の関係を保持する別のテーブルT3に適しています。複数のC1、C2、C3がすでに存在する別のテーブルが存在する場合は、さらに適合します。たとえば、テーブルAからテーブルBの複数の行まで。次に、T3の代わりにBを使用し、 T1からBへの1対1の関係、T2からBへの同じ、AからBへの同じ1対多の関係.

私は正規化はこれに同意しないと信じています、それはそれ以外のアイデアかもしれません:オブジェクトタイプを識別し、同じタイプのオブジェクトを独自のストレージプールに移動し、いくつかのテーブルから1対1の関係を使用し、他のテーブルからのリレーション。

0
Hibou57