Це смішний спосіб структурування схеми БД, чи я щось зовсім пропускаю?


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

ВідділиТаблиця

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 - насправді я ні - я не DBA в торгівлі (на сьогодні явно очевидно! Lol), тому мій поріг SQL WTF досить низький. Хоча, мій повністю пропущений пункт дизайну консультанта змушує мене WTF'ing власні здібності. У вас колись є день, коли ви просто почуваєтесь німим ?
Джим

9
@Jim: Вітаємо, ти перетворив німий день на просвітлений день.
Уейн Коортс

3
Проклинайте цих високооплачуваних консультантів!
davidsleeps

Відповіді:


73

Здійснює для мене ідеальний сенс. Це просто дуже нормалізовано, що надає велику гнучкість, яку б у вас не було. Денормалізовані дані - це біль в області попереку.


Ваша відповідь має ідеальний сенс, і переглядаючи моє запитання та схему, можливо, мене бентежило саме велика кількість таблиць, які він використовує. Я значно спростив приклад свого запитання, але бачу, як концепція звучить - він просто розщеплює речі набагато більше, ніж я. Зітхніть, я гадаю, це добре, що я не DBA! :)
Джим

Навчіться конструювати за десятихвилинним правилом: «Те, що справджується зараз, ймовірно, не пройде через десять хвилин». Переконайтеся, що ваші дизайни можуть боротися зі змінами.
Blrfl

1
Ця схема фактично має таку перевагу, що коли співробітник вставляється, їх відділ повинен існувати.
Саймон Richter

@SimonRichter: Це неправда. Співробітник може бути створений без будь-якого відділу, а також зворотного.
Даніель Дінніс

@SimonRichter Перевага цієї конструкції полягає, по-перше, у тому, що Департамент є окремою сутністю, по-друге, у тому, що між Департаментом та Співробітником існують багато-багато стосунків, на відміну від прикладу ОП, де це було "багато- до одного-іш "(не можна сказати багато-до-одного, як жоден окремий орган Департаменту, на який він посилався, називався відносинами).
Даніель Дінніс

48

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

Причиною таблиці таблиць є те, що якщо ви не помістите відділи в окрему таблицю, вам доведеться мати справу з користувачами у відділах "Продажі", "Продажі", "Продавці", "Патрила" та "Продаж", якщо ви щось не зробите, щоб запобігти цьому. А наявність додаткової таблиці - це (частина) найкращий спосіб, з якого я це знаю.

Чи має бути таблиця UserDepartment - це більш жорсткий дзвінок, що, звичайно, означає, що жодне рішення не є вихідним і божевільним. З одного боку, це біль, коли весь дизайн та логіка ваших таблиць припускали один відділ на кожного користувача, а потім це змінюється, а з іншого - робити додаткове приєднання без причин протягом багатьох років і років - це реальна можливість, а також біль.

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

EDIT - Ключовим рушієм того, чи слід підтримувати відносини «багато до багатьох», є, якщо правила бізнесу чіткі. Якщо ви не знаєте, як користувач у декількох підрозділах навіть працюватиме, немає великого сенсу додавати таблицю, оскільки ваш код не може правильно обробити випадки, коли користувач перебуває у кількох відділах.

Уявіть, що ви дозволяли багато відділів на користувача, про всяк випадок. Потім ви застосували ділове правило щодо призначення комісій на основі департаменту. Тоді було дозволено кілька відділів. На щастя, ви також мали передбачення написати свій код комісії таким чином, щоб це врахували. На жаль, ви додали комісії з кожного відділу для користувачів обох. Керівництво хотіло, щоб ви базувались на ролі осіб для кожного продажу. Отже, наскільки добре було заздалегідь мати стіл? Що з іншими таблицями, які у вас були «про всяк випадок», які взагалі ніколи не потрібні?

ПОСЛІДНА РЕДАКЦІЯ - Ще одна причина, за якою консультант, можливо, захотів би додати всі ці посередницькі таблиці, розглядається в цьому подальшому запитанні , відповіді на яке дають деякі причини, чому переробляти базу даних зазвичай важче, ніж код рефакторингу, який, як правило, підштовхне вас до підхід "помістити у всі таблиці, які вам можуть знадобитися".


Я думаю, ви сказали словами, що таке мій WTF - хлопець використовує TONS цих невідповідних таблиць, і мені це просто здалося таким дурним. Тепер, коли я розбив її на набагато менший приклад для цього питання, я вважаю себе досить дурним, щоб розмістити його, оскільки це не здається таким поганим.
Джим

5
Як ви бачите за багатьма коментарями, існує здоровий скептицизм щодо коментарів "коли-небудь буде лише один X на Y". Консультант покриває себе від скарг "як може виникнути лише один X на Y". Деякі з яких, мабуть, з’являться. Але він не несе відповідальності за підтримку коду, який має багато приєднань (не надто погано, але важче), і це має бути правильним щодо правил бізнесу, які ще не існують (погано) - уявіть собі питання "чому користувачі отримують ВСЕ дозволи від кожного відділу, вони повинні отримувати НАЙМИСЛІший з кожного дозволу "або щось подібне.
пн

@psr Я думаю, що є помилка: не повинні "запити, які передбачають, що є лише один користувач на відділ", "запити, які передбачають, що користувач перебуває лише в одному відомстві"?
BiAiB

@BiAiB - ти прав, це те, що я мав на увазі сказати.
пн

14

Якщо вимога полягає у наявності декількох відділів на користувача, ця конструкція має сенс. Єдине рішення про це - UserDepartmentTableнаявність сурогатного ключа, UserDepartmentIDякий не потрібен (просто зробіть UserIdі DepartmentIdскладений первинний ключ).

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


18
... Доки не можливо більше одного відділу на кожного користувача.
Blrfl

1
Саме так, @Blrfl. Сьогодні не буде, що завтра відбудеться, це завтра генеральний директор, який має аневризму, тому що це не робить.
Адам Кросленд

2
Частиною вирішення того, що гідне такого виду лікування, є розуміння проблемної області. У деяких додатках може бути важливо знати, що працівник № 3804 був відомий компанії як Ен Сміт та Ен Джонс (після одруження), що зробило б нормалізацію імені зі столу працівників доброю справою. У випадку Джима, можливо, варто розширити таблицю вимикачів, щоб зберегти історію, так що якщо Енн перейде від HR до ІТ, той факт, що старий запит, пов'язаний з нею, може відображати, що це дійсно запит HR, а не ІТ.
Blrfl

8
YAGNI - бази даних можуть бути відновлені.
JeffO

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.Activeна помилковий, і створює нову асоціацію, яка є активною). Можливо також встановити версію асоціації відділів за допомогою моделі двох таблиць (лише користувач та відділ), але це жорсткіше і потребує додавання хоча б ще одного стовпчика або проведення акробатики бази даних, щоб уникнути дублювання первинних ключів.
  • Це дозволяє досить легко призначати асоціації «один-багато» чи «багато-до-одного» або «багато-до-багатьох».

Попри це, є кілька причин НЕ робити те, що зробив ваш високооплачуваний консультант.

  • Усі перераховані вище переваги є передчуттям можливих майбутніх потреб, надто ускладнюючи речі на сьогоднішній день. Це не сумісне з YAGNI. Пізніше мігрувати складно, щоб записати міграцію, яка переходить від вашої двосторонньої моделі до моделі таблиці приєднання. Це можна зробити, коли з’явиться потреба в бізнесі. Робити це до цього може бути заплутано.
  • Це бентежить інших розробників. Хоча, так, я б сказав, що очікування для веб-розробника вашого статусу (де ви переглядаєте рішення консультантів) було б зрозуміти та визнати таблицю приєднання, це все-таки складніше, ніж потрібно, і враховуючи відсутність потреби в бізнесі, це викликає плутанину.

приємний аналіз - однак, я б не сказав, що у мене в роботі щоденний робочий день, але хіба що я єдиний тут, хто щось знає про db / c # / vb / і т. д. ... тож здогадуюсь, що я частина time dev за замовчуванням це досить невеликий проект, тому консультанти великої кількості таблиць і приєднань залишили мене сказати "wtf" (але завдяки тобі чудовий народ, я зараз кажу "oic ...")
Jim

Досить стара тема, але все ще актуальна ... Рефакторинг може бути дуже важким, уявіть, що вам потрібно буде кілька відділів у майбутньому замість одного, але мати лише ідентифікатор відділу в Користувачах як FK. Ви, швидше за все, отримаєте дублікати арбітрів (Users.DeptID і UsersDepartmentsTable) або повне сміття, як-от відокремлені комами списки в Users.DeptID або XML. Правильне рішення не може бути легко додано, як пропонують YAGNI або KISS, але воно буде перешкоджати.
Ерік Харт

0

Без повної структури потрібної інформації я не можу сказати, страшно це чи ні. Але принаймні показаний твір не має дизайну "WTF". Це просто здається, що 3-а нормальна форма структури даних (ну, теоретично, у нас також є 4-а та 5-а також)

Деякі переговори можуть мати місце для UserDepartmentTable між двома школами "природних" та "штучних" клавіш на зображеному фрагменті. Більше нічого, як я бачу

Нормалізація - це правило хорошого розробника / дизайнера БД з багатьох причин, * de * нормалізація використовується іноді в середині розробок для більшої швидкості

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.