Пошук уроків, статей та іншого контенту
Навчитеся обирати сховище за вимогами до даних, навантаження, масштабування, доступності та узгодженості.
База даних визначає, як система зберігатиме, змінюватиме та читатиме інформацію. Неправильний вибір може призвести до:
повільних запитів;
складного масштабування;
втрати або дублювання даних;
надмірних витрат на інфраструктуру;
складної підтримки системи.
Не існує універсальної «найкращої» бази даних. Вибір залежить від вимог конкретної системи.
Потрібно оцінити:
структуру даних;
типи запитів;
навантаження;
потребу в масштабуванні;
вимоги до доступності;
вимоги до узгодженості даних.
Реляційні бази даних зберігають інформацію в таблицях, які складаються з рядків і стовпців.
Приклади:
PostgreSQL;
MySQL;
MariaDB;
SQLite.
Реляційна модель добре підходить, коли:
дані мають чітку структуру;
між сутностями є зв’язки;
потрібні складні запити;
важлива узгодженість;
операції мають виконуватися атомарно.
Наприклад, інтернет-магазин може мати такі сутності:
користувачі;
товари;
замовлення;
позиції замовлення;
платежі.
Замовлення пов’язане з користувачем, а позиції замовлення — із товарами. Реляційна база даних добре описує такі зв’язки.
Документні бази даних зберігають записи у вигляді документів, часто у форматі, схожому на JSON.
Приклади:
MongoDB;
CouchDB.
Документний підхід зручний, коли:
структура записів може змінюватися;
дані природно представлені вкладеними об’єктами;
найчастіше потрібно отримувати весь документ;
зв’язків між даними мало або їх не потрібно часто обробляти.
Наприклад, профіль користувача може містити налаштування, список адрес і параметри сповіщень в одному документі.
Водночас документні бази даних не завжди зручні для складних зв’язків між багатьма сутностями.
Сховища типу «ключ-значення» зберігають значення за унікальним ключем.
Приклади:
Redis;
Amazon DynamoDB у режимі ключ-значення.
Таке сховище підходить, коли програмі потрібно швидко отримати значення за відомим ключем:
сесію користувача;
кеш результату;
лічильник;
тимчасий код підтвердження;
стан обробки завдання.
Наприклад:
session:user-42 -> { "userId": 42, "expiresAt": "2026-09-02T12:00:00Z" }Якщо основний запит системи має вигляд «знайди значення за ключем», ключ-значення може бути хорошим вибором.
Першим кроком потрібно з’ясувати, наскільки стабільною та складною є структура даних.
Якщо кожен запис має однакові поля, реляційна база даних часто буде природним вибором.
Наприклад, для товару можна визначити:
id;
name;
price;
stock;
created_at.
Обов’язкові поля, типи даних і обмеження можна описати схемою.
Якщо різні записи мають різні поля, документна база даних може бути зручнішою.
Наприклад, характеристики товарів можуть відрізнятися:
для ноутбука важливі обсяг пам’яті та діагональ екрана;
для взуття — розмір і матеріал;
для книжки — автор і кількість сторінок.
Проте гнучка структура не означає відсутність правил. Навіть у документній базі даних потрібно визначити, які поля є обов’язковими та як вони перевіряються.
Потрібно оцінити, чи мають дані багато зв’язків.
Реляційні бази даних добре працюють із запитами на кшталт:
знайти всі замовлення користувача;
знайти всі товари певної категорії;
отримати замовлення разом із його позиціями;
порахувати загальну суму продажів.
Якщо дані часто потрібно поєднувати, фільтрувати та агрегувати, реляційна база даних зазвичай спрощує розробку.
Якщо ж програма майже завжди працює з одним самодостатнім записом, документи можуть бути зручнішими.
Навантаження описує, скільки операцій система виконує за певний час.
Потрібно окремо оцінити:
кількість операцій читання;
кількість операцій запису;
розмір даних;
розмір окремого запису;
пікове навантаження;
складність запитів.
Якщо дані читаються набагато частіше, ніж змінюються, можуть допомогти:
індекси;
кешування;
репліки для читання;
спеціалізоване сховище для швидкого доступу.
Але спочатку потрібно перевірити запити та виміряти їхню швидкість. Вибір іншого типу бази даних не замінює оптимізацію невдалого запиту.
Якщо система часто змінює дані, важливими стають:
швидкість запису;
блокування;
конфлікти одночасних змін;
порядок обробки операцій;
вимоги до транзакцій.
Наприклад, система оплати має обережно обробляти одночасні зміни балансу. Тут узгодженість часто важливіша за максимальну швидкість запису.
Середнє навантаження може бути невеликим, але під час розпродажу, трансляції або популярної події кількість запитів різко зростає.
Потрібно запитати:
чи повинна система працювати під час піку;
чи допустиме тимчасове сповільнення;
чи можна відкласти частину операцій;
чи може база даних автоматично збільшувати ресурси.
Масштабування — це збільшення здатності системи обробляти дані та запити.
Вертикальне масштабування означає збільшення ресурсів одного сервера:
процесора;
оперативної пам’яті;
дискового простору;
швидкості диска.
Це простий підхід, який часто достатній для першої версії системи. Проте ресурси одного сервера мають обмеження.
Горизонтальне масштабування означає додавання нових серверів або вузлів.
Це може ускладнити:
розподіл даних;
синхронізацію;
обробку конфліктів;
транзакції;
резервне копіювання;
пошук несправностей.
Не слід обирати складну розподілену базу даних лише через припущення про майбутнє навантаження. Спочатку потрібно оцінити реальні вимоги та очікуване зростання.
Доступність показує, наскільки довго система повинна залишатися працездатною.
Для простої внутрішньої програми короткий простій може бути прийнятним. Для платіжної або комунікаційної системи навіть короткий простій може бути критичним.
Під час вибору потрібно з’ясувати:
чи потрібна робота під час відмови одного сервера;
як швидко система має відновлюватися;
чи потрібні репліки;
як виконуватимуться резервні копії;
скільки даних допустимо втратити після аварії.
Реплікація підвищує доступність, але додає складності. Потрібно враховувати затримку синхронізації та можливість тимчасової різниці між копіями.
Узгодженість означає, що після операції система повертає коректні та очікувані дані.
За сильної узгодженості після успішного запису наступне читання повинно побачити це значення.
Це важливо для:
платежів;
залишків на рахунках;
бронювання місць;
складських залишків;
прав доступу.
Наприклад, якщо залишився один квиток, система не повинна дозволити двом користувачам одночасно його придбати.
За зрештою узгодженої моделі різні копії даних можуть тимчасово містити різні значення, але згодом синхронізуються.
Це може бути прийнятним для:
лічильника переглядів;
стрічки новин;
кешу;
статистики;
рекомендацій.
Якщо користувач побачить кількість переглядів із невеликою затримкою, це зазвичай не є критичною помилкою.
Важливо не плутати доступність із правильністю даних. Система може бути доступною, але повертати тимчасово не найновіше значення.
Транзакція об’єднує кілька операцій в одну логічну дію.
Наприклад, переказ грошей може складатися з двох змін:
зменшити баланс одного рахунку;
збільшити баланс іншого рахунку.
Якщо виконалася лише одна операція, дані стали некоректними. Тому обидві операції повинні виконатися разом або не виконатися взагалі.
Для операцій із такими вимогами реляційна база даних часто є практичним вибором.
Перед вибором потрібно визначити:
чи змінюються кілька записів в одній операції;
чи повинні ці зміни бути атомарними;
що має відбутися в разі помилки;
чи потрібні обмеження на рівні бази даних.
Можна використовувати такий порядок.
Запишіть:
які сутності існують;
які поля вони мають;
які поля є обов’язковими;
які зв’язки між сутностями є важливими.
Не обмежуйтеся переліком сутностей. Запишіть реальні операції:
отримати користувача за ідентифікатором;
знайти замовлення за користувачем;
отримати товари категорії;
оновити залишок;
підрахувати статистику.
База даних повинна відповідати не лише структурі даних, а й основним запитам.
Для кожної операції запитайте:
чи повинні всі читання бачити останнє значення;
чи допустима затримка синхронізації;
чи потрібна транзакція;
які наслідки помилки або дублювання.
Приблизно визначте:
кількість користувачів;
кількість запитів за секунду;
співвідношення читання та запису;
розмір даних зараз;
очікуване зростання.
На початку це можуть бути оцінки. Важливо зафіксувати припущення, а потім перевірити їх вимірюваннями.
Визначте:
допустимий час простою;
допустиму втрату даних;
необхідність автоматичного відновлення;
вимоги до резервних копій.
Не потрібно одразу порівнювати десятки технологій. Для початку достатньо оцінити кілька підходів:
реляційна база даних;
документна база даних;
ключ-значення.
Виберіть найпростіший варіант, який задовольняє вимоги.
Рішення можна описати звичайним об’єктом JavaScript і перевірити простим правилом:
function chooseStorage(requirements) {
if (requirements.requiresTransactions && requirements.hasManyRelations) {
return "Реляційна база даних";
}
if (requirements.readsByKnownKey && requirements.needsVeryFastReads) {
return "Сховище ключ-значення";
}
if (requirements.flexibleSchema && !requirements.hasManyRelations) {
return "Документна база даних";
}
return "Реляційна база даних як початковий варіант";
}
const orderSystem = {
requiresTransactions: true,
hasManyRelations: true,
readsByKnownKey: false,
needsVeryFastReads: false,
flexibleSchema: false
};
console.log(chooseStorage(orderSystem));
// Реляційна база данихЦе не універсальний алгоритм і не замінює тестування. Його мета — показати, як пов’язати вимоги із рішенням.
У реальному проєкті результат потрібно перевірити за допомогою:
тестових запитів;
навантажувальних тестів;
вимірювання затримки;
перевірки відновлення після помилок.
Основні вимоги:
зв’язки між користувачами, товарами та замовленнями;
транзакції для оформлення замовлення;
узгодженість залишків;
складні фільтри та звіти.
Початковим вибором часто буде реляційна база даних.
Основні вимоги:
отримання за відомим ключем;
короткий час відповіді;
автоматичне видалення за терміном дії;
тимчасовість даних.
Для такого сценарію підходить сховище ключ-значення.
Основні вимоги:
різні набори полів для різних типів товарів;
часте отримання всього опису товару;
невелика кількість складних зв’язків.
Документна база даних може бути зручною, якщо запити відповідають структурі документів.
Вибір бази даних завжди містить компроміси.
Зручність одного підходу може означати складність в іншому:
гнучка схема спрощує зміни, але може приховати помилки у структурі;
сильна узгодженість підвищує надійність, але може зменшити доступність під час проблем із мережею;
горизонтальне масштабування збільшує пропускну здатність, але ускладнює систему;
додаткові індекси прискорюють читання, але збільшують вартість запису та використання диска.
Тому потрібно оцінювати не окрему характеристику, а всю систему разом.
Популярність бази даних не доводить, що вона підходить конкретній системі. Спочатку потрібно описати дані та запити.
Не варто одразу будувати складну розподілену систему без підтвердженого навантаження. Це збільшує кількість компонентів і джерел помилок.
Якщо кілька змін мають виконуватися разом, це потрібно врахувати під час вибору. Інакше система може залишати дані в частково зміненому стані.
Одна й та сама інформація може зберігатися в різних моделях. Важливо знати не лише, що зберігається, а й як саме це читається та змінюється.
Повільна система може бути наслідком:
невдалого запиту;
відсутнього індексу;
зайвих мережевих звернень;
неефективної логіки програми.
Заміна бази даних без аналізу причини не гарантує покращення.
Реплікація не завжди замінює резервну копію. Помилково видалені або пошкоджені дані можуть потрапити і в репліки. План відновлення потрібно розглядати окремо.
Вибір бази даних починається з вимог, а не з назви технології.
Реляційні бази даних підходять для структурованих даних, зв’язків і транзакцій.
Документні бази даних зручні для гнучких самодостатніх записів.
Сховища ключ-значення ефективні для швидкого доступу за ключем.
Потрібно враховувати навантаження на читання та запис.
Масштабування може бути вертикальним або горизонтальним.
Висока доступність додає вимог до реплікації та відновлення.
Сильна узгодженість потрібна для критичних операцій, а зрештою узгодженість може підходити для менш важливих даних.
Найкращий початковий вибір — найпростіше сховище, яке задовольняє відомі вимоги.