Нормалізація вирішує одні проблеми, але іноді створює інші, особливо коли мова йде про продуктивність. Сьогодні ми відкриємо для тебе двері у темне (а іноді й світле) мистецтво — денормалізацію. Так, ти можеш порушувати правила нормалізації... але тільки з розумом!
Денормалізація — це процес, протилежний нормалізації. Якщо нормалізація розбиває таблиці на окремі логічні сутності, мінімізуючи надлишковість, то денормалізація обʼєднує дані назад, щоб покращити продуктивність. Денормалізація часто використовується, коли при великих навантаженнях і частому виконанні складних запитів зʼєднання багатьох таблиць починає гальмувати систему.
Можна сказати, що денормалізація — це компроміс між чистотою даних і швидкістю виконання запитів.
Коли використовувати денормалізацію?
Як і з будь-яким інструментом, важливо знати, коли денормалізація доречна. Її застосовують у таких випадках:
Часто використовувані запити стають повільними. Коли система з великим навантаженням часто виконує однакові запити (наприклад, зведені звіти та агрегати), зʼєднання багатьох таблиць може займати значний час. Денормалізація дозволяє зменшити кількість таких зʼєднань.
Аналітичні задачі та статистика. В аналітичних системах (наприклад, BI — Business Intelligence) часто потрібен масивний аналіз даних. У таких випадках денормалізація прискорює обробку завдяки "попередньо підготовленим" даним.
Складні запити. Якщо для виконання запиту доводиться зʼєднувати пʼять, десять чи навіть більше таблиць, це може суттєво сповільнити роботу бази даних. Денормалізація дозволяє спростити структуру запитів.
Кількість зʼєднань перевищує здоровий глузд. Якщо у тебе запити з 25 таблицями в
JOIN, можливо, час переглянути підхід.
Приклади денормалізації
Приклад 1: Інтернет-магазин. У нормалізованій базі даних інтернет-магазину у нас можуть бути такі таблиці:
customers— дані про клієнтів.orders— інформація про замовлення.products— дані про продукти.order_items— товари, що входять у замовлення.
Запит для отримання інформації може виглядати приблизно так:
SELECT
c.customer_name,
o.order_date,
p.product_name,
oi.quantity
FROM
customers c
JOIN
orders o ON c.customer_id = o.customer_id
JOIN
order_items oi ON o.order_id = oi.order_id
JOIN
products p ON oi.product_id = p.product_id
WHERE
c.customer_id = 42;
Але що, якщо наш інтернет-магазин обробляє сотні тисяч замовлень на день? Цей запит стане надто повільним через велику кількість зʼєднань.
Рішення: денормалізація.
Давай створимо таблицю для часто використовуваної інформації:
CREATE TABLE order_summary AS
SELECT
c.customer_id,
c.customer_name,
o.order_id,
o.order_date,
p.product_id,
p.product_name,
oi.quantity
FROM
customers c
JOIN
orders o ON c.customer_id = o.customer_id
JOIN
order_items oi ON o.order_id = oi.order_id
JOIN
products p ON oi.product_id = p.product_id;
Тепер, коли нам потрібно отримати дані, ми просто робимо запит до order_summary:
SELECT * FROM order_summary WHERE customer_id = 42;
Приклад 2: Система аналітики. Уяви, що ти працюєш з базою даних для компанії, яка продає квитки на події. Є таблиці:
events— інформація про події.sales— дані про продажі квитків.
Якщо аналітикам потрібно побудувати звіт про середній дохід з одного квитка по всіх подіях, нормалізована структура змушує тебе виконувати агрегований запит кожного разу:
SELECT
e.event_name,
AVG(s.price) AS avg_ticket_price
FROM
events e
JOIN
sales s ON e.event_id = s.event_id
GROUP BY
e.event_name;
Цей запит може бути досить повільним, особливо якщо запис про кожен продаж займає мільйони рядків.
Рішення: денормалізація. Створимо окрему таблицю з агрегованими даними:
CREATE TABLE event_summary AS
SELECT
e.event_id,
e.event_name,
COUNT(s.sale_id) AS ticket_count,
SUM(s.price) AS total_revenue,
AVG(s.price) AS avg_ticket_price
FROM
events e
JOIN
sales s ON e.event_id = s.event_id
GROUP BY
e.event_id, e.event_name;
Тепер звіти будуть працювати швидше на агрегованому рівні:
SELECT
event_name,
avg_ticket_price
FROM
event_summary;
Наслідки денормалізації
Денормалізація, звісно, може прискорити запити, але це не чарівна паличка, яка вирішить всі проблеми. Ось з чим можна зіткнутися, якщо наважишся на цей крок.
Перше — дублювання даних. Коли одна й та сама інформація зберігається у кількох місцях, розмір бази швидко росте, і з цим стає складніше працювати.
Друге — оновлювати дані тепер складніше. Уяви, у тебе є дані про клієнта в таблиці customers, а ще копія цих даних у таблиці order_summary. Якщо клієнт змінить імʼя чи адресу, треба не забути оновити одразу в двох місцях. Промахнувся — і вийшла помилка, бо дані більше не співпадають.
Третє — через таку надлишковість легко заплутатись і допустити помилки. Це як з різними версіями одного й того ж документа — іноді важко зрозуміти, яка версія правильна.
І нарешті, підтримувати і розвивати таку базу складніше. Доведеться писати спеціальні тригери або скрипти, щоб всі копії даних залишались синхронізованими. Це додаткова робота для розробників.
Коротше, денормалізація — це інструмент, який треба використовувати з розумом, знаючи всі плюси і мінуси.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ