web-dev-qa-db-ja.com

1対1の関係を使用する必要がある場合

Noobの質問で申し訳ありませんが、データベース内のテーブルと1対1の関係を使用する実際のニーズはありますか? 1つのテーブル内にすべての必要なフィールドを実装できます。データが非常に大きくなっても、SELECT *を使用する代わりに、SELECTステートメントで必要な列名を列挙できます。この分離が本当に必要なのはいつですか?

73

1から0..1

  • スーパークラスとサブクラスの間の「1から0..1」は、 継承の実装 の「個別のテーブルのすべてのクラス」戦略の一部として使用されます。

  • 「1〜0..1」は、NULL可能フィールドで覆われた「0..1」部分を持つ単一のテーブルで表すことができます。ただし、リレーションシップがmostly「1 to 0」で、「1 to 1」行が少数の場合、「0..1 「別のテーブルに分割することで、ストレージ(およびキャッシュパフォーマンス)のメリットをいくらか節約できます。一部のデータベースは、他のデータベースよりもNULLの格納がth約されているため、この戦略が実行可能になる「カットオフポイント」はかなり異なります。

1対1

  • 実際の「1対1」はデータを垂直方向に分割するため、キャッシングに影響する可能性があります。データベースは通常、個々のフィールドのレベルではなくページレベルでキャッシュを実装するため、行からいくつかのフィールドのみを選択した場合でも、通常、行が属するページ全体がキャッシュされます。行が非常に広く、選択されたフィールドが比較的狭い場合、実際には必要のない多くの情報をキャッシュすることになります。そのような状況では、データを垂直方向に分割すると便利な場合があるため、onlyより狭く、より頻繁に使用される部分または行がキャッシュされるため、そのうちの1つがキャッシュに収まり、キャッシュを効果的に「大きく」することができます。

  • 垂直分割のもう1つの用途は、ロック動作を変更することです。通常、データベースは個々のフィールドのレベルではロックできず、行全体のみをロックできます。行を分割することにより、その半分の1つだけでロックを実行できます。

  • トリガーも通常、テーブル固有です。理論的にはテーブルが1つだけで、トリガーが行の「誤った半分」を無視するようにできますが、一部のデータベースでは、トリガーが実行できることとできないことに追加の制限を課すことがあります。たとえば、Oracleでは変更テーブルを変更できません。別のテーブルを使用することで、そのうちの1つだけが変更され、トリガーからもう1つを変更できます。

  • 個別のテーブルにより、よりきめ細かなセキュリティが可能になります。

これらの考慮事項はほとんどの場合無関係であるため、ほとんどの場合、「1対1」のテーブルを単一のテーブルにマージすることを検討する必要があります。

89

一方のテーブルのデータが、他方のテーブルに記述されているエンティティに関連しているが、そのエンティティに「属していない」場合、それはそれを分離するための候補です。

個別のデータを他のエンティティにも関連付ける必要がある場合、これは将来的に利点を提供する可能性があります。

17
Sepster

2つの1対1テーブルを1つに配置すると、セマンティクスの問題が発生する可能性があります。たとえば、すべてのデバイスに1つのリモートコントローラーがある場合、そのデバイスとリモートコントローラーをそれらの特性の束とともに1つのテーブルに配置するのはあまり良くありません。特定の属性がデバイスまたはリモートコントローラーに属しているかどうかを判断するのに時間がかかる場合もあります。

カラムの半分が長い間空のままであるか、埋められない場合があります。たとえば、車には特性のあるトレーラーが1つある場合とない場合があります。したがって、多くの未使用の属性があります。

テーブルに20個の属性があり、そのうち4個だけが時々使用される場合、パフォーマンスの問題のためにテーブルを2つのテーブルに分割することは理にかなっています。

そのような場合、すべてを1つのテーブルに入れるのは良くありません。また、45列のテーブルを扱うのは簡単ではありません!

14
superM

私の2セント。

私は全員が大規模なアプリケーションで開発する場所で働いており、すべてがモジュールです。たとえば、usersテーブルがあり、ユーザーのFacebookの詳細を追加するモジュール、Twitterの詳細をユーザーに追加する別のモジュールがあります。これらのモジュールの1つを取り外し、アプリケーションからすべての機能を削除することを決定できます。この場合、すべてのモジュールは、次のように、グローバルusersテーブルに1:1の関係を持つ独自のテーブルを追加します。

create table users ( id int primary key, ...);
create table users_fbdata ( id int primary key, ..., constraint users foreighn key ...)
create table users_twdata ( id int primary key, ..., constraint users foreighn key ...)
12
santiago arizti

これを使用する最も賢明な時間は、この方法でのみ関連する2つの別個の概念がある場合です。たとえば、車には現在のドライバーを1つしか持てず、ドライバーは一度に1台の車しか運転で​​きません。したがって、車とドライバーの概念の関係は1対1になります。ポイント。

もう1つの理由は、概念をさまざまな方法で専門化したいということです。 Personテーブルがあり、Employee、Customer、Shareholderなど、さまざまなタイプのPersonの概念を追加する場合、これらのそれぞれに異なるデータセットが必要になります。それらの間で類似するデータはPersonテーブルにあり、スペシャリスト情報はCustomer、Shareholder、Employeeの特定のテーブルにあります。

一部のデータベースエンジンは、非常に大きなテーブル(多数の行)に新しい列を効率的に追加するのに苦労します。元のテーブルに追加される新しい列ではなく、新しい列を含む拡張テーブルが使用されています。これは、追加のテーブルの使用が疑わしいものの1つです。

また、パフォーマンスまたは読みやすさの問題のために、2つの異なるテーブル間で単一の概念のデータを分割することもできますが、これは最初から始める場合はかなり特殊なケースです。これらの問題は後で明らかになります。

11
Fenton

あまり頻繁ではありません。

何らかのセキュリティを実装する必要がある場合、いくつかの利点があります。したがって、一部のユーザーは一部の列(table1)を表示できますが、他の列(table2)は表示できません。

もちろん、一部のデータベース(Oracle)では、同じテーブルでこの種のセキュリティを実行できますが、そうでないものもあります。

5
Randy

データベースの正規化を参照しています。私が管理しているアプリケーションで考えることができる1つの例は、アイテムです。このアプリケーションにより、ユーザーはさまざまな種類のアイテム(つまり、InventoryItems、NonInventoryItems、ServiceItemsなど)を販売できます。すべてのアイテムに必要なすべてのフィールドを1つのItemsテーブルに保存できますが、すべてのアイテムに共通のフィールドを含むベースItemテーブルを保持し、各アイテムタイプ(インベントリ、NonInventory、など)。そのアイテムタイプのみに固有のフィールドが含まれます。次に、アイテムテーブルには、それが表す特定のアイテムタイプへの外部キーがあります。特定のアイテムテーブルとベースア​​イテムテーブルの関係は1対1になります。

以下は、正規化に関する記事です。

http://support.Microsoft.com/kb/283878

4
Grasshopper

すべての設計質問と同様に、答えは「依存します」です。

いくつかの考慮事項があります。

  • テーブルはどのくらい大きくなりますか(フィールドと行の両方で)?メンテナンスとプログラミングの両方の観点から、あまり一般的ではない他のデータとともにユーザーの名前、パスワードを格納するのは不便です

  • 制約のある結合テーブルのフィールドは、時間が経つと管理が面倒になる可能性があります。たとえば、特定のフィールドに対してトリガーを起動する必要がある場合、そのフィールドが影響を受けているかどうかに関係なく、テーブルの更新ごとにトリガーが発生します。

  • 関係が1:1であることをどの程度確信していますか? This の質問が指摘しているように、物事はすぐに複雑になります。

3
Rob Allen

別のユースケースは次のとおりです。何らかのソースからデータをインポートし、毎日更新することができます。本に関する情報。次に、いくつかの本に関するデータを自分で追加します。次に、インポートしたデータを自分のデータとは別のテーブルに置くのが理にかなっています。

3
Dirk

私は通常、実際には2つの一般的な種類の1:1の関係に遭遇します。

  1. IS-A関係。スーパータイプ/サブタイプ関係とも呼ばれます。これは、ある種類のエンティティが実際に別のエンティティのタイプである場合です(EntityA IS A EntityB)。例:

    • 同じ会社内の会計士、エンジニア、営業担当者の個別のエンティティを持つ個人エンティティ。
    • ウィジェット、RawMaterial、FinishedGoodなどの個別のエンティティを持つアイテムエンティティ.
    • トラック、セダンなどの個別のエンティティを持つ自動車エンティティ.

    これらのすべての状況で、スーパータイプエンティティ(Person、Item、Carなど)にはすべてのサブタイプに共通の属性があり、サブタイプエンティティには各サブタイプに固有の属性があります。サブタイプの主キーは、スーパータイプの主キーと同じです。

  2. 「ボス」関係。これは、個人が組織単位(部門、会社など)の一意のボスまたはマネージャーまたはスーパーバイザーである場合です。組織単位に許可されている上司が1人のみの場合、上司を表す個人エンティティと組織単位エンティティ間に1対1の関係があります。

2
Tripartio

まず、何が別のエンティティを構成するかをモデル化して定義することの問題だと思います。 customersが1つだけのaddressであるとします。もちろん、すべてを単一のテーブルcustomerに実装することもできますが、将来的に彼が2つ以上のアドレスを持つことを許可する場合、それをリファクタリングする必要があります(問題ではなく、意識的な決定を下します) )。

また、テーブルの分割が役立つ可能性のある他の回答で言及されていない興味深いケースを考えることもできます。

繰り返しますが、それぞれcustomersを持つaddressがありますが、今回はアドレスを持つことはオプションです。もちろん、Zip,state,streetなどのNULL- able列の束としてそれを実装できます。しかし、あなたがdo haveのアドレスを与えられたと仮定すると、状態はオプションではなく、Zipはオプションです。単一のテーブルでそれをモデル化する方法は? customerテーブルに制約を使用できますが、別のテーブルに分割してforeign_keyをNULL可能にする方がはるかに簡単です。そうすれば、モデルはentityaddressがオプションであり、Zipがそのエンティティのオプション属性であると言うことで、より明確になります。

1
polvoazul

プログラミングの時、私はこれを1つの状況でのみ遭遇しました。これは、同じ2つのエンティティ(「エンティティA」と「エンティティB」)の間に1対多および1対1の関係がある場合です。

「エンティティA」に複数の「エンティティB」があり、「エンティティB」に「エンティティA」が1つだけあり、「エンティティA」に現在の「エンティティB」が1つだけあり、「エンティティB」に「エンティティA」が1つしかない場合。

たとえば、車には現在1台のドライバーしか持てず、ドライバーは一度に1台の車しか運転で​​きません。したがって、車とドライバーの概念の関係は1対1になります。-@Steve Fentonの回答からこの例を借りました

ドライバーが複数の車を運転できるのは、同時にではありません。そのため、車とドライバーのエンティティは1対多または多対多です。ただし、現在のドライバーが誰であるかを知る必要がある場合は、1対1の関係も必要です。

0
Jo Smo

別のユースケースは、データベーステーブルの列の最大数を超える場合です。次に、OneToOneを使用して別のテーブルを結合できます

0
db303