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


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

1
Эта схема на самом деле имеет то преимущество, что когда сотрудник вставлен, его отдел должен существовать.
Саймон Рихтер

@SimonRichter: Это не правда. Сотрудник может быть создан без какого-либо существующего отдела, а также наоборот.
Даниэль Динниес

@SimonRichter Преимущество этой схемы состоит, во-первых, в том, что Департамент является отдельной структурой, и, во-вторых, в том, что между Департаментом и Сотрудником существует отношение «многие ко многим», в отличие от примера ОП, где «много to-one-ish "(нельзя сказать" многие-к-одному ", так как ни одна отдельная сущность Департамента, на которую она ссылалась, не называлась отношением).
Даниэль Динниес

48

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

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

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

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

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

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

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


Я думаю, вы выразили словами, каким был мой 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 * нормализации используются иногда в середине разработки для скоростного выигрыша в основном

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.