Эффективность проектирования базы данных с ограничением от 1 до многих отношений от 1 до 3 - PullRequest
4 голосов
/ 15 июня 2010

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

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

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

Обновление

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

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

Ответы [ 8 ]

5 голосов
/ 15 июня 2010

Самая большая проблема в том, что ваши запросы становятся более сложными.Скажем, вы хотите найти все аккаунты с балансом более $ 10000 у владельца.В нормализованной БД это будет выглядеть примерно так:

select firstname, lastname, accountnumber, balance
from account
join customeraccount using (accountnumber)
join customer using (customernumber)
where balance>10000

Но с тремя полями accountnumber это становится

select firstname, latname, accountnumber, balance
from account
join customer on customer.accountnumber1=account.accountnumber
  or customer.accountnumber2=account.accountnumber
  or customer.accountnumber3=account.accountnumber
where balance>10000

Каждый запрос, который присоединяет Account к Customer, теперь усложняется, как это.

Рано или поздно кто-то напишет запрос, который не сможет проверить accountnumber3, или он попытается выполнить три теста, скопировав и вставив, и после копирования accountnumber1 два раза он забудет изменить один из них.Это ошибка, которую легко пропустить при чтении запроса.Если вы ошибетесь одним из трех сравнений, программа будет работать для всех клиентов, которые имеют только две учетные записи, но не смогут работать с клиентами, у которых есть три.Это проблема, которая может легко пройти тестирование.

Теперь вам нужно продумать, как именно работают объединения, когда один и тот же клиент имеет несколько учетных записей.Если у клиента есть два соответствующих аккаунта в каком-либо запросе, хотите ли вы, чтобы он появлялся один или два раза?

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

Вы уверены, что максимум никогда не изменится?Потому что, если это когда-нибудь произойдет, теперь каждый из этих запросов, которые проверяют три слота, должен быть изменен, чтобы проверить четыре слота.Это может быть тонна работы.

Что вы получаете в обмен на всю эту боль?Автоматическое применение ограничения max-3.На один столик меньше.Возможно, вы получите лучшую производительность по некоторым запросам, потому что нужно объединить на одну таблицу меньше.С другой стороны, вы можете не получить более высокую производительность, в зависимости от многих деталей внутренней работы механизма базы данных и фактических данных.

В общем, я бы сказал, что это почти наверняка не стоит делать.Придерживайтесь нормализованной базы данных.

Я говорю по опыту.Я сделал что-то очень похожее на это однажды.У нас была база данных, в которой мы должны были записывать три типа «менеджеров» для каждой книги, опубликованной нашей организацией (№ 1, отвечающий за бюджетирование и администрирование, № 2, отвечающий за распространение, и № 3, отвечающий за содержание (т.е. редактор)Так как все три были разными, я создал три отдельных пункта. Огромная ошибка. Мне было бы гораздо лучше создать таблицу диспетчера книг с кодом типа и обеспечить выполнение только одного из каждого типа с помощью триггеров или кода.было намного проще. (Опыт позволяет вам принимать правильные решения. Опыт приобретается благодаря принятию неправильных решений.)

5 голосов
/ 15 июня 2010

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

Добавление четвертой или более учетных записей потребует добавления столбцов в таблицу, что снова приведет к увеличению количества пустых полей для каждой записи.

Во-вторых, будет проще запрашивать данные (например, общее количество учетных записей), если они хранятся в отдельной таблице.

Причина, по которой мы используем отдельные таблицы для отношений от 1 до N, заключается в том, что это избавит вас от таких головных болей, как эти.

3 голосов
/ 15 июня 2010

Преимущества:

  • Быстрее обычной формы (на сколько?)
  • Упрощенные запросы для основных операций (без объединений)
  • Чуть проще установить максимальные ограничения

Недостатки:

  • Расширяемость
  • Добавлена ​​бизнес-логика (Что делать, если клиент закрывает свой первый аккаунт? Сменить другие?)
  • Потраченное впустую пространство (значительно, если у обычного пользователя нет 3 учетных записей)
  • Сложнее получить совокупные показатели (т. Е. Точное количество счетов)
  • Вы не можете утверждать, что ваша БД нормализована

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

Однако , я бы предпочел использовать триггер для наложения лимита учетной записи, поскольку это обеспечило бы простоту обслуживания, а не растрату дискового пространства, и будущие разработчики не будут удивляться, почему Я даже не могу получить 1NF правильно.

1 голос
/ 15 июня 2010

Подход с тремя столбцами страдает, если есть изменение бизнес-правила (то есть: теперь пользователи могут иметь ЧЕТЫРЕ учетные записи, ах ах ах ...).Для этого потребуется оператор таблицы ALTER против INSERT, и для поддержки нового столбца (столбцов) придется пересмотреть всю вспомогательную логику - очень дорого с точки зрения разработки.Кроме того, базы данных имеют ограничение для столбцов , когда 3NF не будет затронут.

1 голос
/ 15 июня 2010

Теперь предположим, что вы собираетесь ограничить пользователя только тремя учетными записями.

Это включает в себя магическое число, которое может быть изменено.не верьте никому, кто говорит, что есть «предел».Сегодняшний абсолютный максимум - это завтрашний минимум.

Не участвуйте в применении этой глупости в базе данных.Все «пределы» являются не более чем «типичными значениями для текущего приложения» и изменятся.

Используйте обычные 1-ко-многим с обычными внешними ключами и игнорируйте магическое число «3».

1 голос
/ 15 июня 2010

Преимущество: более высокая производительность, не требуется присоединений к таблице отношений

Недостаток: нарушает 1-ую нормальную форму (но может быть нарушена из-за более высокой производительности)

все зависит от вас;)

0 голосов
/ 17 июня 2010

звучит так, будто вы все тонете в стакане воды! .. почему бы просто не добавить столбец счетчика в каждую таблицу подробных счетов, а если вы пытаетесь добавить новую строку счета, проверьте счетчик?

0 голосов
/ 15 июня 2010

Возможные недостатки разделения номеров счетов по нескольким столбцам:

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

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

Это не является автоматическим нарушением первой нормальной формы, потому что 1NF - это не что иное, как определение самого отношения.Это просто не очень практичный дизайн ( DRY принцип).

...