Ви не любите тригери?

Ви не любите кішок? Та ви просто не вмієте їх готувати! © Альф
imageПри проектуванні досить об'ємних реляційних баз даних часто приймається рішення про відступ від нормальної форми — «денормалізації».
Причини можуть бути різними. Від спроби прискорення доступу до певних даних, обмежень використовуваної платформи/фреймворку/засобів розробки і до недостатньої кваліфікації розробника/проектувальника БД.
Втім, строго кажучи, посилання на обмеження фремфорка і т. п. — по суті спроба виправдати брак кваліфікації.

Денормализованные дані — слабка ланка, через яке легко можна привести нашу базу у неконсистентное (нецілісне) стан.

Що з цим робити?

Приклад

В базі даних є таблиця з якимись фінансовими операціями: надходження та списання коштів з різними рахунками.
Потрібно завжди знати залишок коштів на рахунку.

У нормалізованих даних залишок коштів — завжди розраховується величина. Підсумовуємо всі надходження мінус списання.

Однак, коли кількість операцій ну дуже велике, то кожен раз розраховувати залишок занадто витратно.
Тому прийнято рішення зберігати актуальні залишки в окремій таблиці. Як оновлювати дані в цій таблиці?

Рішення «як зазвичай»

Практично у всіх інформаційних системах, з якими мені доводилося працювати, це завдання виконувало зовнішнє додаток, в якому реалізована бізнес логіка. Добре, якщо додаток нескладне і точок зміни даних — одна з форми в інтерфейсі. А якщо є якісь імпорти, API, сторонні програми і так далі? І ці речі роблять різні люди, команди? А якщо не одна таблиця з підсумками, а їх кілька в різних розрізах? А якщо ще й не одна таблиця з операціями (зустрічав і таке)?

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

Кішки Тригери

В якості альтернативи для контролю цілісності денормализованных даних «дорослої» СУБД використовують тригери.
Часто доводилося чути, що тригери моторошно уповільнюють базу даних, тому їх використання недоцільне.
Другим аргументом було те, що вся логіка знаходиться в окремому додатку і тримати бізнес логіку в різних місцях теж недоцільно.

Давайте розберемося.

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

update totals 
set total = select sum(operations.amount) from operations where operations.account = current_account
where totals.account = current_account

Запит звертається до таблиці операцій (operations) і підсумовує всі суми операцій (amount) рахунку (account).

Такий запит із зростанням бази даних буде з'їдати все більше і більше часу і ресурсів. Але того ж результату можна добитися, використовуючи «легкий» запит типу:

update totals 
set total = totals.total + current_amount
where totals.account = current_account

Такий тригер при додаванні нового рядка просто збільшить підсумок за рахунком, не розраховуючи його заново, він не залежить від обсягу даних у таблицях. Розраховувати підсумок заново немає сенсу, так як ми можемо бути впевнені, що тригер спрацьовує ЗАВЖДИ при додаванні нової операції.

Аналогічно оброблюється видалення і зміна рядків. Такого типу тригери практично не забаряться операції, але будуть гарантувати зв'язність і целостностность даних.

Завжди, коли я спостерігав «гальма» при вставці даних у таблицю з тригером, це був зразок такого «важкого» запиту. І в переважній більшості випадків вдавалося переписати його в «легкому» стилі.

Бізнес логіка
Тут варто відокремити мух від котлет. Є сенс відрізняти функції, що забезпечують цілісність даних, від власне бізнес логіки. У кожному такому випадку ставлю питання: якщо б дані були нормалізовані, то була б потрібна така функція? Якщо відповідь позитивна — це бізнес логіка. Негативний — забезпечення цілісності даних. Сміливо завертайте ці функції в тригери.

Втім, є думка, що весь бізнес логіку легко можна реалізувати засобами сучасної СУБД, такий як PostgreSQL або Oracle. Підтвердження знаходжу в своєму just-for-fun проект.

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

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

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.