3

データベースを作成していますが、データベースを使用するのはこれが初めてです。

1対1の対応について1つ質問があります。特定のスポーツのチームを表すテーブルを作成しています。

私は、すべてのチームが試合を行うアリーナを 1 つだけ持ち、すべてのチームが独自のアリーナを持つことを望んでいます。

アリーナには多くの属性 (名前、座席、チケット価格など) があるため、1 対 1 の関係を作成するベスト プラクティスはすべてを 1 つのテーブルに入れることだと読んだことがあっても、それらのテーブルを作成します。 .

アリーナとチームは 2 つの異なる概念であるため、次のように 2 つのテーブルに分割します。

Club
--------------------
ClubID (PK)
ClubName
.
.
.
ArenaID (FK)


Arena
--------------------
ArenaID (PK)
ClubID (FK)
ArenaName
Seats
TicketPrice

さらに、クラブが作成されるときにアリーナを自動的に作成するため、ArenaID を AutoIncremental ではなく、ClubID と等しくすることを考えました。それは合理的ですか?

このタイプの関係は、他の場合にも使用されるため、よく理解したいと思います (たとえば、すべてのチームには、スキルを持つアシスタント コーチが常に 1 人います)。

ありがとうございます!

編集:

@Kevin Bowersox私はゲームがどのようになるかを指定しただけでした.あなたの答えに感謝します.

@Peter Gluckアリーナはクラブの属性と考える必要がありますが、アリーナには他の独自の属性があり、データベースをより適切に整理するためにクラブテーブルから分離したいと考えています。クラブが別のアリーナを「建設」したい場合は、実際のアリーナの名前を変更するだけで、座席数とチケット価格を変更できます。ただし、データベースに保存された「オブジェクト」は同じままです。一部の列のみが変更されます。

@Branko Dimitrijevic詳細な回答をありがとう。あなたの言ったことをよりよく理解するために、いくつか質問をしたいと思います(私は今データベースを使い始めています)。最初の例では、両方のテーブルに 2 つのキーを使用せず、一方が主キーで他方が外部キーになりますが、同時に主キーと外部キーである唯一のキーを使用します。それが正しいか?そして、これら2つの選択肢の違いは何ですか? では、チーム数が少ない場合は 1 つのテーブルにまとめた方がよいとおっしゃっていますが、数万 (または数十万) のチームを持つことを望んでいます。この場合、これはテーブルを分割するのに十分な数ですか? これは、このテーブルに 1 対 1 の関係が複数あるためです。これらすべての 1 対 1 の関係を同じテーブルに入れると、非常に大きくなります。

皆さんの提案に感謝します。今度は、2 つのテーブルと 2 つの異なる ID キーでこの方法を使用してみます。しかし、私はypercubeによって提案された方法を他のテーブルで使用します!

4

4 に答える 4

4

これらのテーブルを分割するというアイデアが気に入っています。これにより、オブジェクト モデルの機能が大幅に向上します。

ただし、以下に関して:

さらに、クラブが作成されるときにアリーナを自動的に作成するため、ArenaID を AutoIncremental ではなく、ClubID と等しくすることを考えました。それは合理的ですか?

ArenaID を独自の自動整数として保持します。クラブがアリーナを切り替えるとどうなりますか? これは、これらのキーが同期しなくなる原因となるシナリオの 1 つにすぎません。このアプローチを使用して、これらのキーの一部を手動で調整することになると思います。リレーショナル データベースを維持し、状況に依存しないようにしてください。

于 2013-01-04T20:52:55.460 に答える
1

延期可能な制約をサポートする DBMS では、循環外部キーを使用して真の「1 対 1」を実装できます。

CREATE TABLE Club (
    ClubId INT PRIMARY KEY
    -- Other fields...
);

CREATE TABLE Arena (
    ClubId INT PRIMARY KEY REFERENCES Club (ClubId)
    -- Other fields...
);

ALTER TABLE Club ADD FOREIGN KEY (ClubId)
    REFERENCES Arena (ClubId)
    DEFERRABLE INITIALLY DEFERRED;

FKClub -> Arenaはトランザクションが終了するまで適用されないため、鶏が先か卵が先かという問題に陥ることなくClub挿入できます。Arena


残念ながら、MySQL では遅延制約がサポートされていないため、真の「1 対 1」の関係を実装することはできません。したがって、新しいデータを挿入するときに鶏が先か卵が先かの問題を解決することはできません。真の「1 対 1」に必要な循環 FK の存在。

MySQL は CHECK 制約を適用しないため、提案したソリューションに真に依存することさえできないため、ClubIdとの間の等価性を適用することはできませんArenaId。おそらく最善の方法は、アプリケーション ロジックに依存してそれを強制することであり、潜在的なバグが発生する可能性があります。

代替キー (つまり、UNIQUE 制約) を使用しても、次の理由から役に立ちません。

CREATE TABLE Club (
    ClubId INT PRIMARY KEY,
    ArenaId INT UNIQUE
    -- Other fields...
);

CREATE TABLE Arena (
    ArenaId INT PRIMARY KEY,
    ClubId INT NOT NULL UNIQUE REFERENCES Club (ClubId)
    -- Other fields...
);

ALTER TABLE Club ADD FOREIGN KEY (ArenaId)
    REFERENCES Arena (ArenaId);

INSERT INTO Club (ClubId) VALUES (1);
INSERT INTO Club (ClubId) VALUES (2);
INSERT INTO Club (ClubId) VALUES (3);

INSERT INTO Arena (ArenaId, ClubId) VALUES (1, 2);
INSERT INTO Arena (ArenaId, ClubId) VALUES (2, 3);
INSERT INTO Arena (ArenaId, ClubId) VALUES (3, 1);

UPDATE Club SET ArenaId = 2 WHERE ClubId = 1;
UPDATE Club SET ArenaId = 3 WHERE ClubId = 2;
UPDATE Club SET ArenaId = 1 WHERE ClubId = 3;

これで、別のクラブ ( ClubId = 1) を指すアリーナ ( ArenaId = 2) を指すクラブ ( ) ができましたClubId = 3! 等...

機能したとしても、クラスター化されたテーブルのセカンダリ インデックスは高価になる可能性があり、すべての InnoDB テーブルはクラスター化されています。


あなたが提案した「垂直分割」は、通常、フィールドのサブセットが他のサブセットよりもはるかに多くクエリされ、行数が多い場合に、キャッシュをより有効に利用するために行われます。特殊なクエリ パターンを使用している場合でも、キャッシュの問題に遭遇するチームが十分にあるとは思えません。本当に再考して、すべてを 1 つの表にまとめる必要があります。

于 2013-01-05T01:01:16.913 に答える
0

あなたは概念をよく理解しているように見えます。あなたは確かにあなたの決定を推進するための適切な考慮事項を見ています。あなたが行っている仮定が正しく、正しいままであることを確認してください。(つまり、チームBのアシスタントコーチである個人が別のチームのアシスタントコーチになることは決して許可されませんか?これらの質問に対する答えが常にそうです、すべての関係について、それらは実際に1対1としてモデル化できます(実際、機能を失うことなく、すべてを単一のチームテーブルの属性として配置できます)が、注意してください。前提となることはめったにありません。このように実際に真実であり、アプリケーションとデータモデルが進化するにつれて長期にわたって真実であり続ける運命にあります...

これが実際に1対1であると仮定すると、それらを別々のテーブルに分割することを検討する唯一の理由は、パフォーマンスのためです。1つの(小さい)属性セットが1秒間に数百回アクセスされるのに対し、属性の大部分はかなり安定しており、アクセス頻度ははるかに低いとしましょう。次に、より頻繁にアクセスされる属性をより小さく狭いテーブルに配置して、読み取りと書き込みのパフォーマンスを向上させることができます。純粋に論理的または組織的な美学のために属性を分離することは、私がすることではありません...

于 2013-01-04T20:55:17.193 に答える
0

あなたは(コメントで)こう言います:「チームはそのアリーナの名前と大きさを変えることができるので、アリーナを変えることはできません。したがって、永遠に一対一の関係が存在するでしょう。」

決して、または永遠に言わないでください。要件の変更。

「本質的に異なるオブジェクトは、関係に関係なく独自のキーを持つ必要がある」という @Peter Gluck のコメントに同意します。

前の 2 つの観察に従って、3 つのオブジェクト/エンティティ ( ClubArenaおよび) のすべてについて別のテーブルを保持しますClubPlaysInArena。クラブとアリーナ間の 1 対 1 の関係という (現在の) 制限はUnique、要件が変更された場合に解除できる 2 つの制限によって維持されます。設計にこれ以上の変更は必要ありません。

Club
--------------------
ClubID (PK)
ClubName
.
.

Arena
--------------------
ArenaID (PK)
ArenaName
Seats
.
.

ClubPlaysInArena
--------------------
ClubID  (PK, UQ1, FK1)
ArenaID (PK, UQ2, FK2)
.
.

ボーナス ポイント: 関連するクラブがなくても、新しく建設されたアリーナ (およびアリーナのないクラブ) をデータベースに保存できます。

于 2013-01-06T01:35:17.940 に答える