余分な列を持つ単一のテーブルとスキーマを複製する複数のテーブル


13

私はプロジェクトに取り組んでいます。ある時点で、データベースに、すべてのレコードが使用するわけではない複数の列を持つ単一のテーブル、または複製されたスキーマを持つ複数のテーブルが必要かどうかを決定する必要がありました。

複数のスポーツを処理できるスポーツ情報アプリケーションを作成しています。たとえば、NBA、NHL、MLB、NFLを処理できます。各スポーツには、チーム、スケジュール、怪我、選手情報など、非常に似た概念があります。

もちろん、データソースは同じスキーマ内の各データを提供しません。各スポーツには、ベンダーからデータを受け取る異なるスキーマがあります。

共通性を判断するためにデータフィードの事前分析を行うのに十分な時間(クライアントの要求)がなかったため、賭けをヘッジし、「安全な賭け」を行い、すべてのテーブルのセットの代わりに、スポーツごとに個別のテーブルを作成しました使用されるスポーツ。

その結果、いくつかのテーブルでスキーマが複製され、データベースへのインターフェイス(ストアドプロシージャなど)も複製されます。NBA_Game、NFL_Game、NBA_Team、NFL_Teamなどがあります。各テーブルには、他のテーブルにはないプロパティがいくつかあり、いくつかのプロパティは共有されています。4〜5回のスポーツで5〜10個のテーブルが続きます。これが完全に悪いことであるかどうかはまだわかりません。すべてのスポーツが使用するわけではないプロパティを持つテーブルの単一セットを持つ代替案は、それ自体も扱いにくいかもしれません。

これを行った人は、この種の設計の落とし穴にぶつかり、ここで自分の経験を共有できますか?将来の困難な方法を学ぶのではなく、今私が知るのに役立つかもしれないことは何ですか?すべてのレコードが使用するわけではない列を使用して、1つの大きなテーブル/テーブルのセットを使用して、別の方法でそれを実行しましたか?どんな落とし穴に遭遇しましたか?

過去に使用したテーブル継承など、より適切に機能する代替手段はありますか?

ありがとう

回答:


12

最終的には、使用法とアーキテクチャに帰着します。

建築

システムは「あらゆるスポーツ」を処理しますか?あなたは建築の宇宙飛行士の帽子をかぶって、今日さえ存在しないかもしれない将来のタイプのスポーツを扱うことができる一般的なシステムを構築するという考えですか?

もしそうなら、明らかに動的に名前が付けられたテーブルを持つことは大きな苦痛なので、必要に応じてn個のスポーツをサポートするスキーマを持つことは理にかなっています。

そうは言っても、私はこのアプローチに対して非常に強い偏見を持っています。これはほとんどの場合、より多くの作業であり、より悪い結果につながります。スポーツごとに個別のUI、スキーマなどを作成すると、たとえ表面的な重複を意味する場合でも、最終的にユーザーエクスペリエンスが向上し、コードのメンテナンスが容易になります(これを回避/最小化する方法は別の質問です)。

複数のスポーツをするプレーヤーをどのように扱いますか?彼らは2つのエントリを取得しますか(たとえば、あなたは異なる人々として扱います)、またはあなたはそれらに何か特別なことをしようとしていますか?

使用する

したがって、スポーツを動的に行わないと仮定しましょう(たとえば、誰かが新しいスポーツを追加したい場合、追加するには開発努力が必要です)。

一度に複数のスポーツの選手(またはあなたが言及した他のオブジェクト)を表示することがありますか?

これは、スポーツに関係なくプレイヤー名またはチーム名で検索できる検索機能で見ることができますが、それ以上に多くのユースケースを想像することはできません。

これを行う必要がない場合は、アプローチはまったく問題ありません。ここで読むのをやめることができます。

代替スキーマ

視聴回数

私はKISSのファンです。15年以上にわたるソフトウェア開発の中で、私は「動作する最も単純なものを構築する」という哲学に立ち戻り続けています。

したがって、クロススポーツ検索機能が実際に唯一のユースケースであると仮定した私の最初の反応は、ビューを作成することです。

SELECT PlayerName, 'NFL' as [Sport], TeamName FROM NFL_Players JOIN NFL_Teams ... 
UNION  
SELECT PlayerName, 'NHL' as [Sport], TeamName FROM NHL_Players JOIN NHL_Teams ... 
UNION ....

もちろん、新しいスポーツを追加する場合は、ビューに追加する必要があります。他の一般的な情報を含めることも有用かもしれませんが、実際には表示する必要があるものに依存します。

ビュー定義にすべてのスポーツ固有のものを保持するようにしますので、検索コードに多くのまたは特定のコードが必要になることはありません(/nhl/players/player-namevs へのリンク方法/nfl/...またはアプリがそれを行う方法を知っている場合があります)。

テーブルの継承

テーブルの継承は機能しますが、かなり複雑です。私はそれについて多くの経験を持っていません。実際、評価にかかわるたびに、私はここで提案しているような簡単なことをしたと思います。

個人的には、なぜこれが役立つのかまだわかりませんが、複雑さを正当化する説得力のあるユースケース(私は知らない)があるかもしれません(たとえば、テーブル継承は他のソリューションよりもユースケースを解決します) 。

スポーツ固有の属性の個別のテーブル

playersすべてのスポーツのすべてのプレーヤーに共通の属性を持つ単一のテーブルを作成nhl_players_detailsし、次にプレーヤーの追加情報を含むplayerIdと列を含む別のテーブルセットを作成できます。共通の属性が大量にある場合、または「すべてのスポーツのすべての選手」の多くの用途がある場合、これは理にかなっている可能性があります。

スポーツ固有の属性のキーと値のペア

完全に別のアプローチ:持ってplayers、その後、(一般名などの属性を持つ再び、)表player_data持つテーブルをPlayerIdSportAttributeValue。入力される属性名はスポーツ固有です。これにより、スキーマを変更せずに基本的に新しい属性を追加できます(もちろん、コードはそれらをロード/表示するために知っておく必要があります)。欠点は、整合性が失われることです。値は通常文字列フィールドであるため、アプリコードは復元力があり、文字列valueを特定のデータ型(整数など)に変換する潜在的なエラーを処理する必要があります。

もちろん、この概念はチーム、ゲームなどに適用できます。


レガシープロジェクトのソリューションを検索すると、複数の認証可能なタイプとテーブルが表示されますが、ここで忘れていたビューの言及は、私の研究に別の可能なソリューションを提供するのに役立ちました。ありがとうございました。
FullStackFool

5

あなたはデータベースの正規化について話している。完全なデータモデルのようなものは存在せず、正規化が常に優れているとは限らないことを知って安心できます。正規化により、データモデルとデータベースのパフォーマンスが明確になるという点でコストがかかります。したがって、選択する最適なモデルは、使用要件によって異なります。

表面的には、いくつかの列の余分なオーバーヘッドが不合理に思えないように、あなたの例は概念的には十分似ています(X_Game対Y_GameおよびX_Team対Y_Team)。つまり、各スポーツがテーブルに数十の余分な列を追加しようとすると、実際には扱いにくいでしょう。

その場合、一般的なデータは中央のテーブルに保持され、スポーツ固有のデータはリンクされたデータ構造に保持されるハイブリッドモデルを検討することをお勧めします。何かのようなもの:

table Game {
    gameId int,
    teamId1 int fk,
    teamId2 int fk
}

table HockeyGame {
    gameId int fk,
    penaltyMinutes int
}

table BasketballGame {
    gameId int fk,
    freeThrows int
}

これは私が提案しようとしていたものに加えて、おそらくゲームテーブル内のゲームタイプを示す列です。他のテーブルに参加することで推測できることはわかっていますが、ゲームタイプの数が増えると退屈になり始めます。
ロリーハンター14

絶対に-これは、コア関係と、一般的なデータとスポーツ固有のデータの例をいくつか示したスケルトンモデルです。
Midnotion
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.