db design: учет эффективности при добавлении промежуточного класса в отношение «многие-многие» - PullRequest
1 голос
/ 13 августа 2011

Я понимаю, что промежуточный класс часто вводится для сбора информации в ситуации, когда, например, в команде много игроков, а игрок играет за многие команды на протяжении многих лет.Введенный промежуточный класс - это контракт с количеством элементов, как показано:

Команда -1 ---- N- Контракт -N ---- 1- Игрок

Допустим, однако, что 98% всехзапросы запрашивают только текущую информацию и не заботятся об исторической информации.Учитывая имя игрока, они хотят знать информацию о его текущей команде и, возможно, текущем контракте.

Учитывая вышеизложенное отношение, следует ли сначала просматривать все контракты, чтобы сначала найти текущий, а затемОттуда доступ к информации о команде?Или следует провести оптимизацию с прямой связью между игроком и его текущей командой?

Спасибо

Ответы [ 3 ]

1 голос
/ 13 августа 2011

Если вы уверены, что для каждого игрока в данный момент времени есть только одна команда, вы просто добавляете currentTeam столбец к таблице Player и все. Но помните, что вы должны обновлять его каждый раз, когда обновляете таблицу контрактов! И это должно быть сделано в рамках транзакции, чтобы база данных всегда была согласованной.

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

1 голос
/ 13 августа 2011

Учитывая вышеуказанные отношения, должны ли все контракты быть всегда просмотрел сначала найти текущий, а потом оттуда получить доступ к информации о команде?

Современный оптимизатор запросов сначала будет использовать самый селективный индекс. Предполагая, что player_id находится в этом индексе в пригодной для использования позиции, оптимизатор, вероятно, сначала найдет все строки для этого игрока - а их не будет много, верно? - затем выполнит еще одно сканирование индекса по датам контракта, чтобы найти текущий контракт.

На вашем месте я бы создал представление, которое возвращает только "текущие" строки. Позвольте коду приложения работать против этого представления.

1 голос
/ 13 августа 2011

Кажется, это в контексте какого-то ORM, так что я буду работать с этим. (Даже если это не так, продолжайте читать.)

Объекты полезны для моделирования сложных операций. Например, добавление нового Contract приводит к тому, что с Team, Player s и различными PayCheck s происходят всевозможные сумасшедшие вещи (я сделал последнее, но вы поняли) , Это идеальная вещь для обработки в коде, чем, скажем, в ужасно сложной хранимой процедуре T-SQL.

Но когда дело доходит до запросов , я нахожу, что часто имеет смысл написать представление / предложение / проекцию SQL, которые бесстыдно приспособлены к набору необходимой вам информации. выполнять функцию. Пока вы делаете это для чтения данных, а не для их записи, вы на самом деле не подрываете свою объектную модель; вы просто смотрите по-другому, и вы просто делаете прагматическое замечание, что большую часть времени вам нужна только информация из IPlayerCurrentContractQuery, а не весь список Contract в пределах Player. Так как этот метод называется bajillion раза, вы написали интеграционный тест, чтобы убедиться, что SQL дает правильные результаты, и вы внимательно посмотрели на его план запроса, чтобы убедиться, что он не делает такие ужасные вещи, как таблица сканирует в базу данных. Этот обычно используемый экран в вашем приложении быстрый, и все довольны.

Можно утверждать, что создание такого отдельного запроса является преждевременной оптимизацией, но, вероятно, это не так. Я имею в виду, что если у игрока обычно всего несколько Contract с, то, возможно, не стоит разделять запрос и интерфейс. Высасывание всех Contract из базы данных для их циклического прохождения и извлечения текущего будет хуже, чем выбор правильного в базе данных первым, но если это всего лишь несколько Contract с, то подход «да, я полностью осознаю, что это глупо, но достаточно быстро», вероятно, достаточно хорош, просто двигайтесь дальше. Но если эти Contract растянуты на годы или являются большими объектами, то выделение запроса становится легким делом.

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

Подобная ситуация возникает в моем ответе на этот вопрос .

(Если этот вопрос не касается ORM и на самом деле касается моделирования того, как создаются таблицы, то вы должны убедиться, что у вас есть индекс, охватывающий запрос, который выбирает текущий контракт - например, start и stop даты - и вы в значительной степени сделали это, если у вас действительно исключительные требования к масштабированию, как упомянуто выше. Если вы пишете определенный набор объединений очень часто, то вы можете написать функцию или хранимую процедуру для удаления шаблон.)

Это мой мозг. Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...