одна таблица с дополнительными столбцами и несколькими таблицами, дублирующими схему

13

Я работаю над проектом, в котором в какой-то момент мне нужно было принять решение о том, должна ли в базе данных быть одна таблица с несколькими столбцами, которую использует не каждая запись, или несколько таблиц с дублированной схемой.

Я создаю спортивное информационное приложение, которое может обрабатывать несколько видов спорта. Мы можем обращаться с НБА, НХЛ, MLB, НФЛ, например. Каждый вид спорта имеет очень похожие концепции - команды, расписание, травмы, информация об игроке.

Наш источник данных, конечно, не дает нам каждый фрагмент данных в одной и той же схеме. У каждого вида спорта есть своя схема, по которой мы получаем данные от нашего поставщика.

Поскольку у меня не было достаточно времени (требований клиентов) для предварительного анализа каналов данных, чтобы определить общие черты, я хеджировал свою ставку и принимал «безопасную ставку» и составлял отдельные таблицы для каждого вида спорта вместо одного набора таблиц, которые все спорт используется.

Результатом является дублированная схема в нескольких таблицах, а также дублированные интерфейсы к базе данных (например, хранимые процессы). У меня есть что-то вроде NBA_Game, NFL_Game, NBA_Team, NFL_Team и т. Д. У каждой таблицы может быть несколько свойств, которых нет у другой, и несколько общих. это продолжается, скажем, 5-10 столов в 4 или 5 видах спорта. Я до сих пор не уверен, что это совсем нехорошо - альтернатива, имеющая единый набор таблиц со свойствами, которые могут использоваться не во всех видах спорта, сама по себе также может быть громоздкой.

Кто-нибудь, кто сделал это, столкнулся с подводными камнями такого рода дизайна и мог бы поделиться своим опытом здесь? Вещи, которые могут помочь мне узнать сейчас, вместо того, чтобы изучать трудный путь в будущем? Вы сделали это по-другому, имея одну большую таблицу / набор таблиц со столбцами, которые будет использовать не каждая запись? С какими подводными камнями вы столкнулись?

Есть ли какая-то альтернатива, такая как наследование таблиц, которую вы использовали в прошлом, которая работала лучше?

Благодарность

dferraro
источник

Ответы:

12

В конечном итоге все сводится к использованию и архитектуре.

Архитектура

Система управляет "любым спортом"? Является ли идея, что вы надели свою шляпу астронавта архитектуры, и создать общую систему, которая может обрабатывать любой вид спорта будущего, который может даже не существовать сегодня?

Если это так, очевидно, что наличие динамически именованных таблиц является огромной болью, поэтому имеет смысл иметь схему, которая поддерживает n видов спорта, если это необходимо.

Тем не менее, у меня очень сильный уклон против этого подхода: это почти всегда больше работы и приводит к худшим результатам. Создание отдельного пользовательского интерфейса, схемы и т. Д. Для каждого вида спорта в конечном итоге приведет к улучшению взаимодействия с пользователем и упрощению поддержки кода, даже если это будет означать некоторое поверхностное дублирование (как избежать / минимизировать это отдельный вопрос).

Как вы относитесь к игрокам, которые занимаются несколькими видами спорта? Они получают две записи (например, вы относитесь к разным людям) или вы пытаетесь сделать что-то конкретное с ними?

использование

Итак, давайте предположим, что вы не занимаетесь спортом динамически (например, если кто-то хочет добавить новый вид спорта, для его добавления требуются усилия по разработке).

Было ли когда-нибудь время, когда вы демонстрировали игроков (или любой другой упомянутый вами объект) из более чем одного вида спорта одновременно?

Я мог видеть это для функции поиска, где вы можете искать по игроку или названию команды (независимо от вида спорта), но кроме этого я не могу представить себе много вариантов использования.

Если вам никогда не нужно этого делать, тогда ваш подход вполне подойдет. Вы можете перестать читать здесь.

Альтернативные схемы

Взгляды

Я фанат 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 ....

Конечно, если вы добавляете новый вид спорта, вы должны добавить к виду. Также может быть полезно включить другую общую информацию, но на самом деле это зависит от того, что нужно показать.

Я бы постарался сохранить все виды спорта, относящиеся к спорту, в определении View, чтобы в поисковом коде не требовалось много или какого-либо конкретного кода (кроме того, что, возможно, он знает, как ссылаться на /nhl/players/player-namevs /nfl/...или как это делает ваше приложение).

Таблица Наследование

Наследование таблиц может работать, но довольно сложно. У меня нет большого опыта с этим, и фактически, я думаю, что каждый раз, когда я участвовал в оценке этого, мы заканчивали тем, что делали что-то более простое (как я предлагаю здесь).

Так что лично мне еще предстоит выяснить, почему это было бы полезно, но, возможно, есть убедительный вариант использования (о котором я не знаю), который оправдывает сложность (например, наследование таблиц решает вариант использования лучше, чем любое другое решение) ,

Отдельные таблицы для спортивных атрибутов

Вы можете создать одну playersтаблицу, которая имеет атрибуты, общие для всех игроков всех видов спорта, а затем другой набор таблиц, подобный nhl_players_detailsэтому, содержит идентификатор игрока и столбцы с дополнительной информацией об игроке. Если есть множество общих атрибутов или у вас много вариантов использования «всех игроков из всех видов спорта», то это может иметь смысл.

Пары ключ-значение для спортивных атрибутов

Полностью альтернативный подход: есть playersтаблица (опять же , с общими атрибутами , как имя) , а затем в player_dataтаблице , которая имеет PlayerId, Sport, Attribute, Value. Введенные имена атрибутов будут зависеть от вида спорта. Это позволяет вам по существу добавлять новые атрибуты без изменения схемы (ваш код все равно должен знать, чтобы загрузить / отобразить их, конечно). Недостаток в том, что вы теряете некоторую целостность: значение обычно представляет собой строковое поле, поэтому код вашего приложения должен быть гибким и обрабатывать возможные сбои, преобразуя строку valueв определенный тип данных (например, целое число).

Эта концепция, конечно, может относиться к командам, играм и т. Д.

gregmac
источник
Поиск решения для унаследованного проекта позволит найти несколько аутентичных типов и таблиц. Упоминание о представленных здесь представлениях, о которых я забыл, действительно помогло предложить другое возможное решение для моего исследования. Спасибо.
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
}
Midnotion
источник
Это то, что я собирался предложить, плюс, возможно, столбец в таблице Game, указывающий тип игры. Я понимаю, что это можно сделать, присоединившись к другим столам, но если количество типов игр растет, это становится утомительным.
Рори Хантер
Абсолютно - это просто каркасная модель, иллюстрирующая основные взаимосвязи и некоторые примеры того, что может быть общими данными по сравнению со спортивными данными.
Midnotion