База даних вашого інтернет-магазину: як один повільний запит перетворює покупця на втраченого клієнта
Уявіть: покупець додав товар у кошик, натиснув «Оформити замовлення» - і сторінка зависла на 8 секунд. За цей час він встиг подумати: «А чи варто?». Ще через 3 секунди він закрив вкладку. Назавжди. Ви втратили не сторінку, не картинку, не CSS-файл. Ви втратили клієнта через базу даних, яка не встигла відповісти на запит. І найгірше - ви навіть не знаєте, що це сталося.
Більшість власників інтернет-магазинів обирають хостинг за обсягом диска та оперативною пам'яттю. Але продуктивність бази даних - той невидимий фундамент, на якому тримаються каталоги, фільтри, кошики, історія замовлень і пошук по сайту. Саме тут криється різниця між магазином, що конвертує, і магазином, що дратує.
Чому база даних - вузьке горло вашого магазину
Коли відвідувач заходить на сторінку каталогу з 500 товарами і застосовує фільтр «ціна від 1000 до 3000, колір червоний, розмір M, в наявності» - це не один запит. Це каскад з 5-15 SQL-запитів, що виконуються за частки секунди. Або не виконуються, якщо сервер бази даних перевантажений.
Ось що відбувається «під капотом» типового інтернет-магазину на OpenCart, PrestaShop або WooCommerce при кожному завантаженні сторінки:
- Запит на отримання категорії та її підкатегорій
- Запит на фільтрацію товарів за атрибутами
- Підрахунок кількості товарів у кожному варіанті фільтра
- Отримання цін, знижок, залишків на складі
- Завантаження зображень, описів та метаданих для кожного товару
- Перевірка сесії користувача та вмісту кошика
Тепер помножте це на 200 одночасних відвідувачів. Дешевий shared-хостинг з одним ядром процесора для MySQL? Він навіть не чхне - просто ляже.
MySQL, MariaDB чи PostgreSQL - що обрати і чому це важливо
Це не академічне питання. Вибір СУБД впливає на те, скільки одночасних транзакцій витримає ваш магазин. Ось порівняння для типового e-commerce сценарію:
| Параметр | MySQL 8.0 | MariaDB 10.11 | PostgreSQL 16 |
|---|---|---|---|
| Швидкість простих SELECT | Висока | Висока | Середня |
| Складні JOIN-запити | Середня | Середня-висока | Висока |
| Підтримка CMS для магазинів | WooCommerce, OpenCart, PrestaShop | Всі ті ж (drop-in заміна MySQL) | Magento (частково), Saleor, Medusa |
| Робота під навантаженням (100+ з'єднань) | Потребує тюнінгу | Краща з коробки | Найстабільніша |
| JSON-поля для варіантів товарів | Підтримка є | Підтримка є | Найкраща реалізація |
Якщо ваш магазин працює на WooCommerce або OpenCart - MariaDB часто дає приріст 10-20% продуктивності порівняно з MySQL без жодних змін у коді. Це безкоштовний апгрейд, про який багато хостерів навіть не повідомляють.
Для headless-магазинів на Node.js або Python (Saleor, Medusa) PostgreSQL - безальтернативний вибір. Його оптимізатор запитів обробляє складні каталоги з тисячами варіантів товарів значно ефективніше.
Індекси, кеш запитів і магія innodb_buffer_pool_size
Ось вам реальна історія. Клієнт скаржився, що його магазин на PrestaShop з 12 000 товарів «вмирає» щоразу, коли Google-бот починає індексацію. Причина? Параметр innodb_buffer_pool_size стояв на значенні за замовчуванням - 128 MB. База даних важила 2.4 GB. Тобто MySQL щоразу читав дані з диска замість оперативної пам'яті. Після збільшення буфера до 1.5 GB час відповіді впав з 4.2 секунди до 0.3 секунди. Чотирнадцять разів.
«Правило великого пальця: innodb_buffer_pool_size повинен складати 60-80% від доступної оперативної пам'яті на виділеному сервері бази даних. Якщо ви цього не налаштували - ви фактично їздите на Ferrari з ручним гальмом.» - Percona Performance Blog, рекомендації з оптимізації MySQL
Але буфер - лише початок. Ось чекліст параметрів, які критично впливають на швидкість інтернет-магазину:
- query_cache_type - у MySQL 8.0 його прибрали (і правильно зробили), але для MariaDB він досі корисний при правильному розмірі
- max_connections - 50 з'єднань за замовчуванням - це катастрофа для магазину з трафіком 5000+ на добу
- slow_query_log - увімкніть його негайно, поріг - 1 секунда, і ви здивуєтесь, скільки «повільних монстрів» живе у вашій базі
- tmp_table_size і max_heap_table_size - коли тимчасові таблиці не поміщаються в пам'ять, вони скидаються на диск, і все гальмує
Коли пора виносити базу на окремий сервер
На shared-хостингу веб-сервер, PHP і MySQL живуть на одній машині. Поки у вас 200 товарів і 50 відвідувачів на добу - це нормально. Але є чіткі сигнали, що вашій базі тісно:
- Середній час відповіді сторінки перевищив 2 секунди (перевірте через GTmetrix або Google PageSpeed)
- У логах з'являються помилки «Too many connections» або «Lock wait timeout exceeded»
- Під час імпорту нових товарів сайт для покупців стає недоступним
- Нічний бекап бази кладе сайт на 5-10 хвилин
Якщо ви бачите хоча б два з цих симптомів - час переходити на VPS або хмарний хостинг з окремим інстансом бази даних. Наприклад, Amazon RDS, DigitalOcean Managed Database або Hetzner з виділеним MySQL-сервером. Так, це дорожче на $15-40 на місяць. Але порахуйте, скільки замовлень ви втрачаєте через повільний сайт.
Проста математика: якщо ваш магазин робить 10 продажів на день із середнім чеком $50 і 3% відвідувачів ідуть через повільність - ви втрачаєте приблизно $450 на місяць. Окремий сервер бази даних окупається за перший тиждень.
Реплікація та read-replicas - не тільки для Amazon
Є поширений міф: реплікація бази даних - це щось для корпорацій з мільйонними бюджетами. Ні. Якщо ваш магазин генерує 500+ замовлень на день або каталог перевищує 50 000 товарів, read-replica може стати рятівником.
Як це працює? Основна база (master) обробляє записи: нові замовлення, оновлення залишків, реєстрацію користувачів. А копія (replica) бере на себе читання: відображення каталогу, пошук, фільтри. Навантаження розподіляється. Магазин дихає вільно.
На DigitalOcean або Vultr створити read-replica можна за 10 хвилин і $15 на місяць. На хмарних платформах типу AWS чи Google Cloud - ще простіше. Головне - переконатися, що ваша CMS підтримує розділення read/write запитів. WooCommerce з плагіном HyperDB - так. Magento - з коробки. OpenCart - потребує доробки.
Бекапи бази - не те саме, що бекапи файлів
Останній, але критично важливий момент. Більшість хостинг-провайдерів роблять snapshots всього сервера. Це чудово для файлів, але для бази даних активного магазину такий бекап може бути неконсистентним. Уявіть: snapshot зроблено посередині транзакції оплати. Замовлення створене, а запис про оплату - ні. Відновлення з такого бекапу - це рецепт для головного болю бухгалтера.
Що робити? Використовуйте mysqldump або xtrabackup (від Percona) для створення логічних бекапів. Налаштуйте їх через cron щонайменше двічі на добу. І обов'язково перевіряйте бекапи: раз на місяць розгортайте копію на тестовому сервері. Бекап, який ви ніколи не тестували - це просто файл, що займає місце на диску.
Запитайте себе чесно: коли востаннє ви перевіряли, що ваш бекап бази реально можна відновити? Якщо відповідь «ніколи» або «не пам'ятаю» - саме зараз той момент, коли варто зупинити читання і зайти в панель хостингу. Серйозно. Ваш магазин - це не код і не дизайн. Це дані. І вони живуть у базі, яка заслуговує на більше уваги, ніж ви їй приділяєте.