先日、正規化について考えていましたが、データベースに1対1の関係があるはずがないと思いました。
Name:SSN
?同じテーブルに入れます。PersonID:AddressID
?繰り返しますが、同じテーブルです。
1対多または多対多の適切な中間テーブルを使用して、膨大な数の例を思い付くことができますが、1対1になることはありません。
私は何か明白なものを見逃していますか?
先日、正規化について考えていましたが、データベースに1対1の関係があるはずがないと思いました。
Name:SSN
?同じテーブルに入れます。PersonID:AddressID
?繰り返しますが、同じテーブルです。1対多または多対多の適切な中間テーブルを使用して、膨大な数の例を思い付くことができますが、1対1になることはありません。
私は何か明白なものを見逃していますか?
回答:
通常、1対1の関係は、何らかの理由で大きなエンティティを分割したことを示します。多くの場合、これは物理スキーマのパフォーマンス上の理由によるものですが、データの大きなチャンクが同時に「不明」であると予想される場合(ロジックが1:0の場合)にもロジック側で発生する可能性があります。または1:1、ただしそれ以上)。
論理パーティションの例として:従業員に関するデータがありますが、健康保険を選択した場合に限り、収集する必要があるデータのセットが多くなります。ヘルスカバレッジに関する人口統計データを別のテーブルに保持して、セキュリティの分割を容易にし、保険に関係のないクエリでそのデータを引き回さないようにします。
物理パーティションの例は、複数のサーバーでホストされている同じデータです。私は健康保険の人口統計データを別の状態(HRオフィスなど)に保持し、プライマリデータベースはリンクサーバーを介してのみそれにリンクすることができます...機密データを他の場所に複製することを避け、それを利用できるようにします(ここではまれと仮定して)それを必要とするクエリ。
物理パーティショニングが役立つことができたときにあなたがより大きなエンティティの一貫性のサブセットを必要とするクエリを持っています。
1つの理由は、データベースの効率です。1:1の関係があると、行/テーブルのロック中に影響を受けるフィールドを分割できます。テーブルAに大量の更新があり、テーブルbに大量の読み取りがある(または別のアプリケーションからの大量の更新がある)場合、テーブルAのロックはテーブルBで行われていることに影響しません。
他は良い点を持ち出します。アプリケーションなどがシステムにどのように影響しているかによっては、セキュリティも正当な理由となります。私は別のアプローチを取る傾向がありますが、特定のデータへのアクセスを制限する簡単な方法になり得ます。ピンチで特定のテーブルへのアクセスを拒否するのは本当に簡単です。
スパースネス。データの関係は厳密には1:1ですが、対応する行がすべての行に存在する必要はありません。したがって、2,000万行あり、それらの0.5%のみに存在する値のセットがある場合、それらの列を疎に入力できるテーブルにプッシュすると、スペースを大幅に節約できます。
ランクの高い回答のほとんどは、1対1の関係に対してデータベースのチューニングと最適化の非常に有用な理由を提供しますが、1対1の関係が自然に発生する「実際の」例にのみ焦点を当てたいと思います。
これらの例のほとんどのデータベース実装の1つの重要な特性に注意してください。1対1の関係に関する履歴情報は保持されません。つまり、これらの関係は任意の時点で1対1です。データベース設計者がリレーションシップ参加者の変化を経時的に記録したい場合、リレーションシップは1:MまたはM:Mになります。1対1の性質を失います。それが理解されたので、ここに行きます:
「Is-A」またはスーパータイプ/サブタイプまたは継承/分類関係:このカテゴリは、あるエンティティが別のエンティティの特定のタイプである場合です。たとえば、すべての従業員に適用される属性を持つEmployeeエンティティと、その従業員タイプに固有の属性を持つ特定のタイプの従業員を示すためのさまざまなエンティティ(Doctor、Accountant、Pilotなど)があります。この設計により、複数のnullが回避されます。多くの従業員は、特定のサブタイプの特殊な属性を持っていません。このカテゴリの他の例としては、スーパータイプとしての製品、サブタイプとしてのManufacturingProductおよびMaintenanceSupplyなどがあります。スーパータイプとしての動物とサブタイプとしての犬と猫。オブジェクト指向の継承階層をリレーショナルデータベース(オブジェクトリレーショナルモデルなど)にマッピングしようとするときはいつでも、これはそのようなシナリオを表す一種の関係であることに注意してください。
マネージャー、チェアパーソン、プレジデントなどの「ボス」関係。組織単位には1人のボスしか持つことができず、1人の人物は1つの組織ユニットのボスになることができます。これらのルールが適用される場合、部署の1人のマネージャー、会社の1人のCEOなど、1対1の関係になります。「ボス」の関係は、人だけに適用されるわけではありません。たとえば、会社の本社として店舗が1つしかない場合や、国の首都である都市が1つしかない場合にも、同じ種類の関係が発生します。
希少な資源配分のいくつかの種類が、例えば、1つの従業員は、一度に1つの会社の車を割り当てることができます(たとえば、トラック運転手につき1台のトラック、タクシー運転手につき1台のタクシー、など)。最近、同僚がこの例を教えてくれました。
結婚(少なくとも一夫多妻が違法である法的管轄区域で):一度に一人だけが他の一人と結婚することができます。この例は、会社が従業員間の結婚を記録するときの1:1単項関係の例としてこれを使用した教科書から得ました。
一致する予約:一意の予約が行われ、2つの別個のエンティティとして実行された場合。たとえば、レンタカーシステムは、1つのエンティティで予約を記録し、次に別のエンティティで実際のレンタルを記録する場合があります。このような状況は1つのエンティティとして設計することもできますが、すべての予約が満たされているわけではなく、すべてのレンタルに予約が必要なわけではなく、両方の状況が非常に一般的であるため、エンティティを分離することは理にかなっています。
履歴情報が記録されていない場合にのみ、これらのほとんどが1対1の関係であるという先に述べた警告を繰り返します。したがって、従業員が組織での役割を変更した場合、またはマネージャーが別の部門の責任を負った場合、または従業員が車両を再割り当てされた場合、または誰かが未亡人となって再婚した場合、関係の参加者が変更できます。データベースにこれらの1対1の関係に関する以前の履歴が保存されていない場合、それらは正当な1対1の関係のままです。しかし、データベースが履歴情報(各関係の開始日と終了日を追加するなど)を記録する場合、それらはほとんどすべてM:M関係に変わります。
履歴ノートには2つの注目すべき例外があります。1つ目は、一部の関係が非常にまれに変化するため、通常、履歴情報が保存されないことです。たとえば、ほとんどのIS-A関係(製品タイプなど)は不変です。つまり、変更することはできません。したがって、歴史的記録のポイントは意味がない。これらは常に自然な1対1の関係として実装されます。次に、予約とレンタルはそれぞれ独自の日付を持つ独立したイベントであるため、予約レンタルリレーションシップストアの日付は別々です。エンティティには独自の日付があるため、1:1関係自体に開始日があるのではなく、履歴情報が保存されていても、これらは1:1関係のままです。
あなたの質問は、あなたがそれを語った方法のために、いくつかの方法で解釈することができます。応答はこれを示しています。
現実の世界では、データ項目間に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には、5Sに比べてNULLSを完全に回避できるという利点があります。これは、すべてではないが一部のデータベース設計者にとって重要です。スキーマを6NFに組み込むことを気にしたことはありません。
6NFでは、欠落データは、一部の列にNULLのある行ではなく、省略された行で表すことができます。
テーブルの分割には、正規化以外の理由があります。テーブルを分割すると、パフォーマンスが向上する場合があります。一部のデータベースエンジンでは、実際にテーブルを分割する代わりにテーブルをパーティション分割することで、同じパフォーマンス上の利点を得ることができます。これには、論理設計を理解しやすくし、データベースエンジンに高速化に必要なツールを提供するという利点があります。
主にいくつかの理由で使用しています。1つは、データ変更率の大きな違いです。私のテーブルの一部には、以前のバージョンのレコードを追跡する監査証跡が含まれている場合があります。10列のうち5列の以前のバージョンを追跡するだけで、監査証跡メカニズムを備えた別のテーブルに5つの列を分割する方が効率的です。また、書き込みのみのレコード(たとえば、会計アプリ)がある場合もあります。金額を変更することはできません。誤った場合は、対応するレコードを作成して、間違ったレコードを調整し、修正エントリを作成する必要があります。更新や削除ができないという事実を強制する表に制約がありますが、そのオブジェクトにはいくつかの属性があり、順応性があります。それらは、変更に関する制限なしに別のテーブルに保持されます。私がこれを行うもう1つのときは、医療記録アプリケーションです。一度サインオフすると変更できない訪問に関するデータと、サインオフ後に変更できる訪問に関する他のデータがあります。その場合、データを分割し、ロックされたテーブルにトリガーを設定して、サインオフ時にロックされたテーブルへの更新を拒否しますが、医師がサインオフしていないデータへの更新を許可します。
別のポスターは、1:1が正規化されていないことについてコメントしましたが、状況によっては、特にサブタイピングについては同意しません。従業員テーブルがあり、主キーがSSNであるとします(これは一例です。これが別のスレッドにとって適切なキーであるかどうかに関する議論を保存しましょう)。従業員は、一時的または永続的など、さまざまなタイプにすることができ、永続的である場合は、オフィスの電話番号など、入力するフィールドがさらにあります。これは、type = 'Permanent'の場合にのみnullであってはなりません。第3正規形データベースでは、列はキー、つまり従業員にのみ依存する必要がありますが、実際には従業員とタイプに依存するため、1:1の関係が完全に正常であり、この場合は望ましいです。また、過剰にスパースなテーブルを防ぐことができます。
私が考えることができる最も一般的なシナリオは、BLOBがある場合です。大きな画像をデータベースに保存したいとしましょう(通常、画像を保存する最良の方法ではありませんが、制約により便利になる場合があります)。通常、Blob以外のデータのルックアップを改善するために、Blobを別のテーブルに置く必要があります。
純粋な科学という点では、そうです、それらは役に立たないのです。
実際のデータベースでは、まれにしか使用されないフィールドを別のテーブルに保持すると便利な場合があります。このフィールドだけを使用してクエリを高速化するには、ロックなどを回避するため
継承を使用するOOモデルがあり、継承ツリーをDBに永続化する必要がある状況も考えられます。
たとえば、Bird and Fishクラスがあり、どちらもAnimalから継承しているとします。DBには、Animalクラスの共通フィールドを含む「Animal」テーブルがあり、AnimalテーブルはBirdテーブルと1対1の関係にあり、Fishと1対1の関係にあります。テーブル。
この場合、BirdとFish-propertiesを保持するためにnullを使用できる列を多数含むAnimalテーブルが1つある必要はありません。レコードが鳥を表す場合、Fish-dataを含むすべての列はNULLに設定されます。
代わりに、Birdsテーブルに、Animalテーブルのレコードと1対1の関係にあるレコードがあります。
また、「実際の」データベースの変更よりもリスクが少ない(認識されている)実稼働中のテーブルを拡張する方法でもあります。レガシーシステムで1対1の関係を確認することは、多くの場合、最初の設計後にフィールドが追加されたことを示す良い指標です。
一般的なORMのいずれかでデータを使用している場合は、オブジェクト階層に一致させるために、テーブルを複数のテーブルに分割することができます。
私が1対1の関係を実行すると、それは完全に系統的な理由であり、関係的な理由ではないことがわかりました。
たとえば、ユーザーの予約済みの側面を1つのテーブルに配置し、ユーザーのユーザー編集可能フィールドを別のテーブルに配置すると、これらのフィールドに対する権限に関するルールを論理的に簡単に記述できることがわかりました。
しかし、あなたは正しいです。理論的には、1対1の関係は完全に考案されており、ほとんど現象です。ただし、論理的には、データベースを抽象化するプログラムと最適化が容易になります。
ほとんどの場合、誰かが「まあ、なぜそれが1つではないのか」と尋ねられるまで、デザインは1:1であると考えられますか?概念を互いに時期尚早に分離することは、この一般的なシナリオを見越して行われます。PersonとAddressはそれほど強く結び付けられていません。多くの人が複数のアドレスを持っています。等々...
通常、2つの個別のオブジェクトスペースは、1つまたは両方を乗算できることを意味します(x:many)。2つのオブジェクトが真に、真に1:1だったとしても、哲学的に言えば、それはより多くのis-relationshipです。これら2つの「オブジェクト」は、実際には1つのオブジェクト全体の一部です。
私が1対1の関係を確認できる最も良い理由は、データベース設計のSuperTypeサブタイプです。このモデルに基づいて不動産MLSデータ構造を作成しました。5つの異なるデータフィードがありました。住宅、商業、マルチファミリー、ホテル、土地。
5つの個別のデータフィードのそれぞれに共通するデータを含むプロパティと呼ばれるSuperTypeを作成しました。これにより、すべてのデータ型にわたって非常に高速な「単純な」検索が可能になりました。
5つのデータフィードごとに一意のデータ要素を格納する5つの個別のサブタイプを作成します。各SuperTypeレコードは、適切なSubTypeレコードと1対1の関係でした。
顧客が詳細な検索を必要とする場合は、PropertyResidentialなどのスーパーサブタイプを選択する必要がありました。
私の意見では、1対1の関係は、RDBMSのクラス継承をマッピングします。共通の属性(partentクラスステータスなど)を含むテーブルAがあります。継承された各クラスステータスは、専用の属性を含むAテーブルと1:1の関係を持つテーブルBでRDBMSにマップされます。テーブル名Aには、「キャスト」機能を表す「タイプ」フィールドも含まれています。
バイマリオ
1:1になるものはすべて同じテーブルに保持されるため、正規化を行う場合、1:1の関係は実際には意味がありません。
しかし現実の世界では、それはしばしば異なります。アプリケーションインターフェイスに一致するようにデータを分割することができます。
おそらく、データベースに何らかの型付きオブジェクトがある場合です。
テーブルT1で、列C1、C2、C3…があり、1対1のリレーションがあるとします。大丈夫、正規化された形式です。今度はテーブルT2に、列C1、C2、C3、…(名前は異なる場合がありますが、タイプと役割は同じです)があり、1対1のリレーションもあるとします。T1と同じ理由でT2でも問題ありません。
ただし、この場合は、C1、C2、C3を保持する別のテーブルT3と、T1からT3へ、およびT2からT3への1対1のリレーションが当てはまることがわかります。1つから複数のC1、C2、C3がすでに存在する別のテーブルが存在する場合、さらに当てはまります。たとえば、テーブルAからテーブルBの複数の行までです。次に、T3の代わりにBを使用して、 T1からBへの1対1の関係。T2からBについても同じですが、AからBへの1対多の関係は同じです。
私は正規化がこれに同意しないと信じています、それはそれの外の考えかもしれません:オブジェクトタイプを識別し、同じタイプのオブジェクトをいくつかのテーブルから1対1の関係を使用して独自のストレージプールに移動し、1対複数他のいくつかのテーブルからの関係。
これはセキュリティの目的には不必要ですが、セキュリティチェックを実行するより良い方法があります。ドアを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は、バーンニーを騙した嘘つきのズボンだと言えます。ほんの一例です。
どこでも、2つの完全に独立したエンティティが1対1の関係を共有していました。多くの例があるはずです:
人<->歯科医(1:N、それで間違っている!)
人<->医師(その1:N、それも間違っている!)
人<->配偶者(その1:0 | 1なので、ほとんど間違っている!)
編集:はい、それらはかなり悪い例でした。特に、どちらか一方の0または1ではなく常に1:1を探していた場合はなおさらです。私の脳は誤って発火していたと思います:-)
だから、もう一度やってみます。少し考えた結果、(ソフトウェアに関しては)常に一緒になければならない2つの個別のエンティティを作成する唯一の方法は、それらをより高いカテゴリで一緒に存在させることです。そして、もしあなたがより低い分解に陥った場合に限り、物事は分離されるべきであり、分離されるべきですが、より高いレベルではそれらはお互いなしでは生きることができません。コンテキストが鍵となります。
医療データベースの場合、身体の特定の領域に関するさまざまな情報を保存し、それらを個別のエンティティとして保持することができます。その場合、患者の頭は1つだけで、頭が必要か、患者ではありません。(彼らはまた、1つの心臓、および他のいくつかの必要な単一の臓器を持っています)。たとえば、手術の追跡に関心がある場合は、各リージョンを一意の個別のエンティティにする必要があります。
生産/在庫システムでは、車両のアセンブリを追跡している場合、エンジンの進行状況を車体とは異なる方法で監視する必要がありますが、1対1の関係があります。ケアはエンジンを1つだけ持つ必要があります(または、「車」ではなくなります)。エンジンは1台の車にのみ属します。
いずれの場合も、個別のエンティティを1つの大きなレコードとして生成できますが、分解のレベルを考えると、それは誤りです。これらは、これらの特定のコンテキストでは、真に独立したエンティティですが、上位レベルではそれほど表示されない場合があります。
ポール。