Чи можна розробити базу даних з колонками, які могли б суперечити один одному

Припустимо, я розробляю базу даних для страхової компанії з такими двома таблицями:

Користувачі

CustomerID, CustomerName

Політики

PolicyID, CustomerID, EffectiveDate, ExpirationDate

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

З одного боку, це покращить продуктивність моїх запитів, і це буде виглядати чистіше і легше зрозуміти.

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

Це погана практика?

7
Схоже, ви говорите про щось подібне: денормалізація
додано Автор Blorgbeard, джерело
Це класичне компромісне запитання: так, уведення стовпця active полегшує ваше життя з точки зору запитів - чи варто? Інші запитання дійсно інтенсивно обчислюють? Це важливо? І наскільки важливо для вашого бізнесу, що це "активність клієнта?" Відповідь завжди, у будь-який даний момент, абсолютно правильний? Наскільки поганими будуть наслідки (і наскільки дорогі, потенційно), якщо ваша система відповість "так!" для клієнта, який більше не працює, о 15:34 у будь-який робочий день? Це компроміс - потрібно зробити + документ !
додано Автор marc_s, джерело
Питання 1: чи існує значне поліпшення продуктивності? Запитання 2: Чи не можна їх синхронізувати в режимі реального часу? якщо ні, чи існує реальна ймовірність того, що деякий запит може бути неправильним, якщо вони виконуються, якщо вони несумісні?
додано Автор Darius X., джерело
Яким чином ви очікуєте, що це покращить ефективність ваших запитів? Я думаю, що є або нульовий ефект, або він фактично уповільнить ваші запити.
додано Автор G Mastros, джерело
Я думаю, що легше розробити, якщо ви не повинні приєднуватися до таблиці політик щоразу, коли ви хочете фільтрувати за статусом, особливо якщо клієнт може мати кілька політик (від 1 до 1 проти 1 до 1)
додано Автор landons, джерело
Я не бачу причин для цього. Запит, який ви зробите, щоб оновити стовпець Active , буде використовуватись, коли ви хочете дізнатися, чи є клієнт активним чи ні. Я б не пішов цим шляхом.
додано Автор Math, джерело

9 Відповіді

Як кажуть сутінки, це звичайна практика.

Проте, денормалізація має певні витрати - вам слід винайти альтернативний спосіб зберегти "активну" колонку в актуальному стані, і цей процес запровадить більше коду і, отже, можливості для невдачі.

Загалом, я настійно рекомендую денормалізувати, якщо ви знаєте, що у вас є проблеми з продуктивністю. Додаткова приєднання до таблиці Policies майже напевно не матиме відчутного впливу на продуктивність вашої системи, доки ви не досягнете сотні мільйонів записів. Якщо ви стурбовані, побудуйте тестову базу даних і використовуйте інструмент, як DBMonster, щоб заповнити його тестовими даними, і написати запит, який вам потрібно; оптимізуйте їх якомога більше, і тільки якщо ви не можете отримати потрібну ступінь продуктивності, слід враховувати денормалізацію.

6
додано

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

Further reading at: https://en.wikipedia.org/wiki/Database_normalization

5
додано

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

Однак, ви не надаєте достатньо інформації, щоб відповісти на це питання.

Ось два різні сценарії. Клієнти додають, видаляють та змінюють політику щодня. Більшість баз даних присвячена оперативній проблемі збереження актуальних даних. Більшість запитів знаходяться на рівні політики. Іноді потрібно робити звіти про активність клієнта з певних причин. Ну, в цьому випадку, здається, не варто докласти зусиль, щоб змінити структуру даних для "випадкових" запитів. Належна увага полягає в тому, що дані оновлюються.

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

Завдання, яку я маю у вашій ситуації, полягає в тому, що ви, здається, розробляєте базу даних як для транзакційних цілей (високо нормалізовані), так і для звітності (часто менш нормалізовані). Вони не обов'язково добре змішуються. Ось така проста причина. Ви запускаєте цікавий запит звітів, який займає п'ять хвилин. За ці п'ять хвилин для запиту заблоковано одну або кілька таблиць. Або запит займає годину, оскільки оновлення регулярно блокує використовувані таблиці.

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

Ви також повинні дізнатися про тригери, які можуть зберігати таку інформацію актуальною навіть в операційній системі. І про обчислені стовпці і перегляди, які є способами доступу до загальної інформації, не зберігаються безпосередньо в стовпцях.

2
додано

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

  • побудувати функцію або збережену процедуру в базі даних, яка виконуватиме обчислення за допомогою двох полів дати

або

  • build a function або method in the lanaguage being used that calculates active based on the stабоed fields.
1
додано

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

Єдина перевага, яку надає запропоноване рішення, полягає в тому, що вона надає певну ясність вираження при спробі визначити, чи є клієнт активним. Щоб отримати таку ясність виразу, не створюючи головного болю оновлення, можна скористатися переглядом:

CREATE VIEW CustomerStatus (CustomerID, IsActive) AS
  SELECT CustomerID, (IIF(MAX(ExpirationDate))) >= GET_TODAYS_DATE()
  GROUP BY CustomerID

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

1
додано

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

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

Отже, моя думка: залиште її так, як ви її маєте.

1
додано

Я вважаю, що так. Дизайн вашого БД суперечить. Це завжди рекомендується, щоб ви зберігати DB чистою. Крім того, зберігайте БД в максимально нормальному вигляді.

Тут, замість періодичного оновлення прапора "Активний", можна зробити одну річ. Перш за все додайте стовпець "Active Till" у таблицю Customers. ніж при додаванні запису в політиці, потрібно перевірити, що [дата закінчення терміну дії] в таблиці "Клієнти" є раніше, ніж [дата закінчення терміну дії] поточного доданого запису. Якщо так, змініть його на «Дата» відповідно до «поточного запису для політик». Якщо ні, просто не змінюйте його. А коли потрібно перевірити, чи активний користувач, просто прочитайте стовпець "Активні до" і вирішіть.

1
додано

Якщо критерії, які ви визначили, є єдиним критерієм для того, щоб вони були активними, я б сказав, що це добре, щоб просто перевірити рядок Політики для клієнта.

У випадку, якщо існує набагато більше логіки або дорогої логіки для обчислення їхнього активного стану, то краще обчислити це як частину процесу і зберегти його в активному полі в таблиці клієнтів.

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

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

1
додано

Окрім коментаря від @ duskwuff ...

Я переглядаю щось simialr на даний момент в базі даних MS SQL, і я рекомендую ввести наступний термін в Google:

Database Normalization -oracle -mysql -db2

Природно, якщо ви використовуєте Oracle або MySql поміняти ці твердження з -microsoft або щось подібне. Частина цього вмісту трохи суха, але вона допомогла мені в організації поточного проекту бази даних, над яким я працюю.

0
додано
IT KPI - Databases
IT KPI - Databases
162 учасників