Это нелепый способ структурировать схему БД или я что-то упустил?

61

Я проделал немалую работу с реляционными базами данных и думаю, что довольно хорошо понимаю основные концепции хорошего проектирования схем. Недавно мне была поручена работа над проектом, в котором БД был разработан высокооплачиваемым консультантом. Пожалуйста, дайте мне знать, если мой внутренний инстинкт - "WTF ??!?" - гарантированно, или этот парень такой гений, что действует из моего царства?

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

Таблица пользователей:

UserID (primary Key, indexed, no dupes)
FirstName
LastName
Department

Запросить таблицу

RequestID (primary Key, indexed, no dupes)
<...> various data fields containing request details
UserID -- foreign key associated with User table

Просто, правда?

Консультант разработал это так (с примерами данных):

UsersTable

UserID  FirstName   LastName
234     John        Doe
516     Jane        Doe
123     Foo         Bar

DepartmentsTable

DepartmentID   Name
1              Sales
2              HR
3              IT

UserDepartmentTable

UserDepartmentID   UserID   Department
1                  234      2
2                  516      2
3                  123      1

RequestTable

RequestID   UserID   <...>
1           516      blah
2           516      blah
3           234      blah

Вся база данных построена следующим образом, каждая часть данных инкапсулирована в свою собственную таблицу с числовыми идентификаторами, связывающими все вместе. По-видимому, консультант читал об OLAP и хотел получить «скорость целочисленных поисков».

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

Это допустимый дизайн для базы данных SQL малого и среднего размера?

Спасибо за комментарии / ответы ...

Джим
источник
12
О, боже, если это заставит вас сказать WTF, то вы, вероятно, не видели таблиц с 200+ столбцами и хранимых процедур длиной более 1000 строк.
Работа
42
+1 за отсутствие удаления после смущения. Спасибо, что оставили это, чтобы другие могли учиться.
Уэйн Коортс
2
@ Job - на самом деле, я не имею - я не адвокат по профессии (на данный момент довольно очевидно! Lol), поэтому мой порог SQL WTF довольно низок. Хотя из-за того, что я полностью упускаю из виду дизайн консультанта, у меня есть свои собственные способности. Когда-нибудь был день, когда вы просто чувствуете себя глупым ?
Джим
9
@Jim: Поздравляю, ты превратил немой день в просветленный день.
Уэйн Коортс
3
Прокляните тех высокооплачиваемых консультантов!
Дэвид спит

Ответы:

73

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

Blrfl
источник
Ваш ответ имеет смысл, и, глядя на мой вопрос и схему, возможно, меня смутило просто количество таблиц, которые он использует. Я значительно упростил пример для моего вопроса, но я вижу, как концепция звучит - он просто разделяет вещи гораздо больше, чем я. Вздох, я думаю, это хорошо, что я не администратор! :)
Джим
Научитесь проектировать по правилу десяти минут: «То, что верно сейчас, вероятно, не произойдет через десять минут». Убедитесь, что ваши проекты могут справиться с изменениями.
Blrfl
1
Эта схема на самом деле имеет то преимущество, что когда сотрудник вставлен, его отдел должен существовать.
Саймон Рихтер
@SimonRichter: Это не правда. Сотрудник может быть создан без какого-либо существующего отдела, а также наоборот.
Даниэль Динниес
@SimonRichter Преимущество этой схемы состоит, во-первых, в том, что Департамент является отдельной структурой, и, во-вторых, в том, что между Департаментом и Сотрудником существует отношение «многие ко многим», в отличие от примера ОП, где «много to-one-ish "(нельзя сказать" многие-к-одному ", так как ни одна отдельная сущность Департамента, на которую она ссылалась, не называлась отношением).
Даниэль Динниес
48

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

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

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

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

РЕДАКТИРОВАТЬ - Ключевым фактором, определяющим, следует ли поддерживать отношения «многие ко многим», является ясность бизнес-правил. Если вы не представляете, как будет работать пользователь из нескольких отделов, добавление таблицы не имеет особого смысла, поскольку ваш код не может правильно обрабатывать случаи, когда пользователь находится в нескольких отделах.

Представьте, что вы допустили много отделов на пользователя, на всякий случай. Затем вы внедрили бизнес-правило для назначения комиссий на основе отдела. Тогда несколько отделов были разрешены. К счастью, у вас также было предвидение, чтобы написать свой код комиссии таким образом, чтобы это учитывалось. К сожалению, вы добавили комиссионные от каждого отдела для пользователей в обоих. Менеджмент хотел, чтобы вы основывались на роли людей для каждой продажи. Итак, насколько хорошо было заранее иметь стол? А как насчет других таблиц, которые у вас были «на всякий случай», которые вообще не нужны?

ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ - Другая причина, по которой консультант мог бы захотеть добавить все эти промежуточные таблицы, рассмотрена в этом последующем вопросе , ответы на который дают некоторые причины, по которым рефакторинг базы данных обычно сложнее, чем рефакторинг кода, что может привести к подход «вставь все таблицы, которые тебе могут понадобиться».

PSR
источник
Я думаю, вы выразили словами, каким был мой WTF - парень использует тонны этих промежуточных таблиц, и мне это показалось настолько глупым. Теперь, когда я разбил его на гораздо меньший пример для этого вопроса, я чувствую себя довольно глупо, если опубликовать его, так как это не кажется таким уж плохим.
Джим
5
Как вы можете видеть по многим комментариям, существует здоровый скептицизм в отношении комментариев «будет когда-либо только один X на Y». Консультант покрывает себя от «почему может быть только один X за Y» жалоб. Некоторые из которых, вероятно, подойдут. Но он не будет нести ответственность за поддержку кода, который имеет много объединений (не так уж плохо, но сложнее) и который должен быть корректным по отношению к бизнес-правилам, которые еще не существуют (плохо) - представьте себе вопрос «почему пользователи получают ВСЕ разрешения от каждого отдела, они должны получить наименьшее из каждого разрешения "или что-то подобное.
PSR
@psr Я думаю, что есть опечатка: «не должны ли« запросы, предполагающие, что в каждом отделе есть только один пользователь », быть« запросами, предполагающими, что пользователь находится только в одном отделе »)?
BiAiB
@BiAiB - вы правы, именно это я и хотел сказать.
PSR
14

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

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

Одед
источник
18
... Пока на одного пользователя не может быть более одного отдела.
Blrfl
1
Точно, @Blrfl. Сегодняшний случай, который никогда не случится, - это завтрашний день генерального директора, у которого аневризма, потому что он этого не делает.
Адам Кроссленд
2
Частью принятия решения о том, что стоит такого рода лечения, является понимание проблемной области. В некоторых приложениях может быть важно знать, что сотрудник № 3804 был известен компании как Энн Смит и Энн Джонс (после вступления в брак), что сделало бы нормализацию имени из таблицы сотрудников нормальным делом. В случае Джима, возможно, стоило бы расширить таблицу прерывателей, чтобы сохранить историю, чтобы, если Энн перешла от HR к IT, тот факт, что старый связанный с ней запрос мог отражать, что это действительно запрос HR, а не IT.
Blrfl
8
YAGNI - базы данных могут быть реорганизованы.
Джефф
2
@Oded, Некоторые сопоставители ORM, такие как Entity Framework, плохо работают с таблицами, которые имеют составной первичный ключ.
maple_shaft
5

Некоторые требования не ясны в вашем вопросе. Правильный ответ зависит от того, что хочет ваш клиент. На вашем месте я бы спросил этого клиента:

0-Какая разница между пользователем и сотрудником?

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

2-Может ли группа сотрудников сделать 1 запрос?

3-Может ли сотрудник принадлежать к нескольким отделам? Как насчет генерального директора

4-Есть ли подмножество сотрудников, которым разрешено делать запросы?

5-Что происходит с запросом, когда запись сотрудника удаляется (если вообще)?

6-Не могли бы вы удалить запрос? Что происходит, когда запрос удален (убедитесь, что вы не удаляете запись сотрудника по RI)

7-Может ли сотрудник делать «один и тот же» запрос более одного раза (определить «один и тот же»)

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

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

Без шансов
источник
+1 это замечательные вопросы, которые необходимо прояснить перед разработкой схемы такого типа. Мне нравится ваш поток логики.
@ Surfer513: Я ценю ваш хороший комментарий.
NoChance
1

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

  • Правильно проиндексированный (например, если UserDepartmentTable индексирует два внешних ключа), такая таблица объединения имеет небольшую потерю производительности из-за того, что внешние ключи не являются уникальными. Если внешние ключи гарантированно будут уникальными, то из-за небольшой теории баз данных, которую я знаю, поиск UserDepartmentTable.Departmentне более «труден», чем поиск любого другого столбца в Userтаблице.
  • Таблица соединений дает вам больше гибкости для настройки другой информации об ассоциации между пользователем и отделом (например, метки времени при создании).
  • Таблица соединений позволяет довольно легко «проверять» связь (например, когда пользователь меняет отделы, запускает некоторый логический флаг индекса, например, UserDepartmentTable.Activefalse, и создает новую активную связь). Возможно также создание версий ассоциации отделов с использованием модели из двух таблиц (только «Пользователь» и «Отдел»), но это сложнее и требует добавления как минимум еще одного столбца или выполнения акробатики базы данных, чтобы избежать дублирования первичных ключей.
  • Это позволяет довольно легко назначать ассоциации «один ко многим» или «многие к одному» или «многие ко многим».

При этом есть несколько причин НЕ делать то, что сделал ваш высокооплачиваемый консультант.

  • Все вышеперечисленные преимущества предвосхищают возможные будущие потребности, усложняют ситуацию на сегодняшний день. Это не соответствует YAGNI. Позже будет довольно просто написать миграцию, которая переместится из вашей модели двух таблиц в модель таблицы соединений. Вы можете сделать это, когда возникнет потребность в бизнесе. Делать это до этого может быть непонятно.
  • Это смущает других разработчиков. Хотя да, я бы сказал, что для веб-разработчика вашего уровня (где вы просматриваете решения консультантов) стоит ожидать понимания и распознавания таблицы соединений, это все же более сложно, чем необходимо, и учитывая отсутствие потребности бизнеса, это вызывает путаницу.
Стивен
источник
хороший анализ - тем не менее, я бы не сказал, что у меня есть какой-то статус разработчика в моей повседневной работе, за исключением того, что я здесь единственный, кто знает что-либо о db / c # / vb / etc ... так что, думаю, я часть время разработки по умолчанию. это довольно маленький проект, поэтому консультанты из-за большого количества таблиц и объединений заставили меня сказать «wtf» (но благодаря вам, замечательные люди, я теперь говорю «oic ...»)
Джим,
Довольно старая тема, но все еще актуальная ... рефакторинг может быть очень сложным, представьте, что в будущем вам понадобится несколько отделов вместо одного, но в Users как FK есть только идентификатор отдела. Скорее всего, вы получите дублирующиеся ссылки (Users.DeptID и UsersDepartmentsTable) или полный мусор, например разделенные запятыми списки в Users.DeptID или XML. Правильное решение не может быть легко добавлено, как предложено YAGNI или KISS, но будет затруднено.
Эрик Харт
0

Без полной структуры необходимой информации я не могу сказать, ужасно это или нет. Но, по крайней мере, показанный образец не имеет дизайна "WTF". Это выглядит как 3-я нормальная форма структуры данных (ну, теоретически у нас также есть 4-я и 5-я)

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

Нормализация - это правило хорошего DB-разработчика / дизайнера по многим причинам, * de * нормализации используются иногда в середине разработки для скоростного выигрыша в основном

Ленивый Барсук
источник