MariaDB проти PostgreSQL на VPS: налаштування для максимальної швидкості за гроші

Було корисно?

На VPS бази даних рідко «гучно ламаються». Вони ламаються дорого. Спочатку кажуть «сайт здається повільним», потім «потрібен більший інстанс», і врешті хтось тихо виявляє, що ви платили за ОЗП, яке база даних не вміла ефективно використовувати, і за IOPS, які ви ніколи не тестували.

Ось реальність VPS: шумні сусіди, кредит на бурст, непостійна затримка зберігання і жорстка бюджетна межа. У такому світі «швидкість за гроші» — це не скріншот бенчмарку. Це здатність тримати передбачувану p95‑латентність, поки ваш фіндиректор тримає вас на повідку.

Що насправді означає «швидкість за гроші» на VPS

Люди говорять «продуктивність», ніби це одне число. На VPS це купа компромісів і режимів відмов. Якщо ви хочете швидкість за гроші, потрібно визначити, яку саме «швидкість» ви купуєте:

  • Передбачувана затримка (p95/p99), а не лише середня пропускна здатність.
  • Ефективність на один vCPU, коли CPU посередній і спільний.
  • Пишева ампліфікація та поведінка fsync, коли обмеження — сховище.
  • Операційні витрати: як часто доводиться турбувати людину через простій у обслуговуванні.

MariaDB і PostgreSQL обидві можуть бути швидкими. Різниця в тому, як вони поводяться, коли VPS «не ідеальний». PostgreSQL має тенденцію бути чеснішим щодо роботи, яку потрібно виконати (видимість, VACUUM, WAL). MariaDB/InnoDB може бути приголомшливо лояльною для OLTP з великою часткою читань, але вона також може приховувати проблеми — поки не настане день, коли вже не зможе.

Коротка думка (з застереженнями)

Якщо ви на скромному VPS і хочете найбільшу швидкість за гроші для типового SaaS OLTP (багато невеликих читань/записів, прості join‑и, багато одночасних сесій), PostgreSQL зазвичай виграє у довгостроковій перспективі, бо залишається послідовним при «брудних» навантаженнях і дає кращі інструменти для діагностики й контролю системи.

Якщо ваше навантаження орієнтоване на читання, просте за схемою, і вам потрібна гарна продуктивність з мінімальним тюнінгом, MariaDB може бути дешевшою у використанні на малому залозі — особливо коли ви тримаєте більшість «гарячих» даних у innodb_buffer_pool_size і уникаєте сильних конфліктів записів.

Застереження, що має значення: у багатьох провайдерів VPS варіативність затримки зберігання домінує. У такому випадку «швидша база» — та, яку ви можете налаштувати так, щоб уникати синхронних зависань без втрати коректності. PostgreSQL має сильні дефолти цілісності; MariaDB можна налаштувати так, щоб вона ставала страшенно швидкою, якщо послабити стійкість, що може бути прийнятно — до того дня, коли ні.

Просте правило: якщо ви ставите компанію на базу даних і хочете, щоб вона була «нудною», обирайте PostgreSQL. Якщо ви намагаєтеся витиснути максимум за мінімум і вимоги до стійкості гнучкі, MariaDB може стати дешевшим «гонковим болідом».

Жарт №1: VPS схожий на коворкінг: кава нормальна, Wi‑Fi «спільний», і хтось завжди запускає крипто‑майнер через пару столів.

Факти й історія, що досі впливають на налаштування

Це не факти для вікторини. Вони пояснюють, чому певні регулятори існують, чому дефолти виглядають консервативними, і чому міграції іноді відчуваються як переселення під час урагану.

  1. MVCC‑дизайн PostgreSQL (multi‑version concurrency control) був центральним з 1990‑х. Саме тому читання не блокують записи і чому VACUUM — це реальна операційна турбота.
  2. InnoDB став дефолтним рушієм MySQL наприкінці 2000‑х, бо він забезпечив транзакції, блокування на рівні рядка та відновлення після аварії, необхідні в продакшні.
  3. MariaDB відгалузилася від MySQL після поглинання Sun компанією Oracle. Та подія — чому «drop‑in replacement» став аргументом і чому деякі кути сумісності й досі гострі.
  4. Реплікація PostgreSQL еволюціонувала від відправки WAL. Історія реплікації тісно пов’язана з WAL, fsync і налаштуваннями чекпойнтів — ключовими для «швидкості за гроші» на повільних дисках.
  5. У MySQL видалили query cache (а історія MariaDB різниться за версіями). Це причина, чому ви іноді бачите старі поради, що нині активно шкодять конкуренції.
  6. Планувальник PostgreSQL культивує правильність над несподіваною «хитрістю». Він не завжди обирає найшвидший план, але зазвичай він пояснюваний — а це важливо о 3 ранку.
  7. Doublewrite buffer InnoDB існує через ризик часткових записів сторінок. На ненадійному VPS‑сховищі цей захист може врятувати — але за рахунок додаткових операцій запису.
  8. PostgreSQL прийняв розширення (наприклад, pg_stat_statements) як першокласні операційні інструменти. Це радикально змінює щоденний досвід відладки.

Де VPS шкодять базам даних (і чому це змінює вибір)

1) Сховище — це збирач податків

На VPS ви можете купити більше vCPU і більше ОЗП, а база даних все одно зависне на fsync. Суть не в «SSD vs HDD». Суть у хвостовій латентності: кілька повільних синхронізацій за секунду можуть зламати ваш p99. PostgreSQL і MariaDB обидві покладаються на журнали попереднього запису (WAL / redo logs). Як тільки пристрій для журналу глюкне — ваша база даних перетвориться на систему черг з емоціями.

2) «Steal» CPU — це реальність

Віртуалізація може «відбирати» CPU‑цикли (буквально як steal time). Якщо ваш інстанс дешевий, потоки бази даних можуть виконуватись ривками. Це шкодить PostgreSQL, коли є забагато активних з’єднань і багато перемикання контексту. Це шкодить MariaDB, коли потоки purge/flush не справляються і брудні сторінки накопичуються.

3) ОЗП — і золото, і пастка

ОЗП — найдешевший множник продуктивності — поки ви його не перевитратите. PostgreSQL використовує пам’ять на підключення для сортувань/хешів; MariaDB теж використовує буфери на потік, але InnoDB buffer pool — ключовий важіль. На малих VPS одне невірне налаштування пам’яті може викликати свопінг, і тоді ви тестуєте Linux VM‑підсистему, а не базу.

4) Сіткова джиттерність впливає на сприйняту швидкість

Багато звітів «база повільна» насправді стосуються варіативності мережі між аплікацією і БД. PostgreSQL і MariaDB реагують однаково: запит швидкий; запит не доходить. Якщо ваш додаток і БД не колокалізовані, «швидкість за гроші» перетворюється на «затримка за розкаяння».

MariaDB на VPS: у чому її переваги

Коли MariaDB зазвичай виграє по вартості

  • OLTP орієнтований на читання із великою кількістю невеликих точкових пошуків (за первинним ключем / індексовані читання).
  • Прості схеми, де ви не користуєтеся складними SQL‑фічами.
  • Команди з «MySQL‑пам’яттю», які можуть безпечно працювати з ним без «креативного» тюнінгу.
  • Навантаження з передбачуваними патернами доступу, коли buffer pool тримає гарячі сторінки в пам’яті.

Регулятори, що мають значення (і чому)

На VPS продуктивність MariaDB живе й помирає завдяки InnoDB:

  • innodb_buffer_pool_size: зробіть його достатнім, щоб вмістити гарячу робочу множину. Якщо замалий — платите за випадкові I/O. Якщо забагато — ядро починає агресивно відтискати і ви отримуєте паузи.
  • innodb_flush_log_at_trx_commit: дефолт — найбезпечніший (1). Зниження (2 чи 0) дає швидкість, приймаючи втрату даних при аварії. Це не «безкоштовна оптимізація», це бізнес‑рішення.
  • innodb_log_file_size / innodb_redo_log_capacity: більші журнали зменшують тиск чекпойнтів і згладжують записи. Надто великі — довший час відновлення; надто малі — циклічні чекпойнти і навантаження на сховище.
  • innodb_io_capacity: сказати InnoDB, на що реально здатне ваше сховище, щоб він не був ні лінивим, ні скаженим.

Де MariaDB може тихо з’їдати ваші гроші

MariaDB може виглядати швидкою, поки накопичує борг: брудні сторінки, відставання purge, затримка реплікації, яка «поки що» нормальна, до моменту відмови, або одна гаряча таблиця, що перетворює систему в фестиваль м’ютексів. Ви не завжди помічаєте це, поки не впадете з обриву.

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

PostgreSQL на VPS: у чому її переваги

Коли PostgreSQL зазвичай виграє по вартості

  • Змішані навантаження: читання, записи, аналітичні запити і «продукт вирішив, що нам потрібна звітність» в одній базі.
  • Складні запити, де якість планувальника і варіанти індексування мають значення.
  • Операційна прозорість: вбудована статистика і культура інспекції.
  • Довгострокова підтримуваність: передбачувана семантика, менше «залежить від рухуна».

Регулятори, що мають значення (і чому)

Тюнінг PostgreSQL на VPS здебільшого про: (1) уникнення перевитрат пам’яті, (2) згладжування WAL/checkpoints, (3) підтримку здорового VACUUM.

  • shared_buffers: не «якомога більший». На Linux надто великий може виснажити файловий кеш і нашкодити. Зазвичай 15–25% ОЗП — адекватний старт на VPS.
  • work_mem: на сортування/хеш, на вузол, на запит. Якщо виставити його як герой, ваша машина може OOM‑нути як антагоніст.
  • effective_cache_size: каже планувальнику, який кеш ймовірно доступний (OS cache + shared_buffers). Це не алокує пам’ять, але впливає на плани.
  • checkpoint_timeout, max_wal_size, checkpoint_completion_target: можуть перетворити «періодичні стрибки латентності» на «нудьгу». Нудьга — це добре.
  • autovacuum settings: autovacuum — це ваш сусід, що прибирає. Якщо ви його вимкнете, вам сподобається атмосфера, поки сміття не нагромадиться.

Де PostgreSQL може марнувати ваш бюджет

Найбільша пастка — керування підключеннями. Тисячі клієнтських підключень на малому VPS змусить Postgres витрачати ресурси на контекстні переключення і пам’ять, а не на запити. Якщо ви не використовуєте пулер, ви купите більший інстанс лише для розміщення неактивних з’єднань. Це не «масштабування». Це субсидування поганих практик.

Жарт №2: Вимикати autovacuum, бо він «використовує CPU», — це як зняти пожежний сигнал, бо він шумить.

Цитата, що відповідає робочому життю

Вернер Фогельс (CTO Amazon) сказав: «Все ламається весь час.»

Швидкий план діагностики

Коли продуктивність падає на VPS, ваша задача не гадати. Ваша задача швидко локалізувати вузьке місце, а потім вирішити, чи ви обмежені CPU, пам’яттю, I/O, або страждаєте від конкуренції й чергування.

По‑перше: підтвердіть форму симптомів

  • Шаблон спайків затримки: періодичні (чекпойнти, VACUUM, бекапи) проти тривалих (I/O‑навантаження, блокування).
  • Охоплення: один запит/таблиця чи все одночасно.
  • Час на відновлення: секунди (бурст) чи години (заборгованість у обслуговуванні).

По‑друге: вирішіть, що головний лімітатор

  1. Сховище: високий iowait, довгі fsync, низький IOPS, довгі черги диска.
  2. CPU: високий user/sys, високий steal, черга виконання > ядр.
  3. Пам’ять: свопінг, треш кешу сторінок, OOM kills, великі пропуски робочої множини.
  4. Блокування/конкуренція: очікування на лока, contention буферів, забагато підключень.

По‑третє: оберіть категорію «виправлення»

  • Якщо обмежено сховищем: згладжуйте чекпойнти/WAL/redo, уникайте fsync‑штормів, зменшуйте випадкові читання через кеш/індексацію, розгляньте окремий том для логів.
  • Якщо обмежено CPU: зменшіть паралельність, виправте повільні запити, додайте індекси, уникайте per‑row функцій, обережно налаштовуйте паралелізм.
  • Якщо обмежено пам’яттю: правильно розміркуйте буфери, зменшіть work_mem / буфери на потік, впровадьте пулінг, зупиніть свопінг.
  • Якщо обмежено конкуренцією: скоротіть довжину транзакцій, усуньте гарячі рядки, перегляньте порядок блокувань, рівень ізоляції, зробіть кращі індекси, пакуйте записи.

12+ практичних завдань: команди, виводи, рішення

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

Завдання 1: Перевірте steal CPU і iowait (чи VPS вам бреше?)

cr0x@server:~$ mpstat -P ALL 1 5
Linux 6.1.0 (vps01)  12/29/2025  _x86_64_  (4 CPU)

12:00:01 AM  CPU   %usr %nice %sys %iowait %irq %soft %steal %idle
12:00:01 AM  all   22.10  0.00  6.12  18.33 0.00  0.55   8.40  44.50
...

Значення: %steal ≈ 8% означає, що ваші «4 vCPU» не завжди у вашому розпорядженні. %iowait ≈ 18% каже, що домінують затримки сховища.

Рішення: Не тюньте SQL спочатку. Почніть зі згладжування I/O (WAL/checkpoints/redo) і зменшіть кількість конкурентних писачів. Якщо steal лишається високим — розгляньте інший клас VPS/провайдера, перед тим як купувати більше ядер.

Завдання 2: Знайдіть черги диска і затримки (чек на «чому p99 жахливий»)

cr0x@server:~$ iostat -x 1 5
Linux 6.1.0 (vps01)  12/29/2025  _x86_64_

Device            r/s   w/s   rkB/s   wkB/s  await  aqu-sz  %util
vda              85.0  60.0  3400.0  5200.0  22.5    1.80   98.0
...

Значення: await 22.5ms і %util 98% вказують на насичене сховище з постійною чергою (aqu-sz ≈1.8).

Рішення: Ви обмежені I/O. Пріоритизуйте зменшення частоти fsync‑ів, збільшення попадань у кеш і видалення зайвих записів (індекси, детальні логи). Розгляньте переміщення WAL/redo на швидший диск, якщо можливо.

Завдання 3: Підтвердіть файлову систему та опції монтування (barriers, atime, discard)

cr0x@server:~$ findmnt -no SOURCE,FSTYPE,OPTIONS /var/lib
/dev/vda1 ext4 rw,relatime,errors=remount-ro

Значення: ext4 з relatime — нормально. Якщо ви бачите екзотичні опції або мережеві файлові системи, зупиніться і подумайте.

Рішення: Тримайте все звичним. Якщо atime увімкнено (не relatime/noatime), розгляньте noatime для інтенсивного читання. Уникайте «тонкого» тюнінгу опцій монтування, яких ви не розумієте; база даних і так вже робить логіку цілісності.

Завдання 4: Виявлення свопінгу та тиску пам’яті

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           8.0Gi       6.9Gi       120Mi       180Mi       1.0Gi       420Mi
Swap:          2.0Gi       1.6Gi       420Mi

Значення: Ви інтенсивно свопите; «available» низький. Затримка бази стане нелінійною.

Рішення: Зменшіть налаштування пам’яті зараз (Postgres work_mem/shared_buffers; MariaDB buffer pool + буфери на потік). Розгляньте додавання ОЗП лише після перевірки, що немає витоку пам’яті через шторми підключень.

Завдання 5: Перевірте пам’ять процесів і OOM kills

cr0x@server:~$ dmesg -T | tail -n 8
[Mon Dec 29 00:10:12 2025] Out of memory: Killed process 2113 (postgres) total-vm:5242880kB, anon-rss:3100000kB, file-rss:0kB, shmem-rss:0kB
[Mon Dec 29 00:10:12 2025] oom_reaper: reaped process 2113 (postgres), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

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

Рішення: Виправте конфігурацію пам’яті і впровадьте пулінг підключень негайно. Не звинувачуйте планувальник запитів; це базова дисципліна по ємності.

Завдання 6: PostgreSQL — знайти топ‑запити за сумарним часом (припиніть гадати)

cr0x@server:~$ sudo -u postgres psql -d appdb -c "SELECT queryid, calls, total_exec_time::bigint AS total_ms, mean_exec_time::numeric(10,2) AS mean_ms, rows, left(query, 80) AS q FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 5;"
 queryid  | calls | total_ms | mean_ms | rows | q
----------+-------+----------+---------+------+-----------------------------------------------
 91230123 | 12000 |   980000 |   81.67 |  120 | SELECT * FROM orders WHERE user_id=$1 ORDER BY created_at DESC LIMIT $2
 11223344 |  1500 |   410000 |  273.33 |    1 | UPDATE inventory SET qty=qty-$1 WHERE sku=$2
...

Значення: Маєте невелику кількість «тяжкої» активності. Перший запит ймовірно потребує композитного індекса. UPDATE може бути гарячою точкою через contention.

Рішення: Оптимізуйте топ‑1–3 запити перед тим, як чіпати глобальні регулятори. Індекси та переписування запитів переважно кращі за «більше shared_buffers» у більшості випадків.

Завдання 7: PostgreSQL — перевірте, на що очікуєте (локи vs I/O vs CPU)

cr0x@server:~$ sudo -u postgres psql -d appdb -c "SELECT wait_event_type, wait_event, count(*) FROM pg_stat_activity WHERE state='active' GROUP BY 1,2 ORDER BY 3 DESC;"
 wait_event_type |     wait_event      | count
-----------------+---------------------+-------
 IO              | DataFileRead        |    12
 Lock            | relation            |     4
 LWLock          | buffer_content      |     3

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

Рішення: Збільшіть попадання в кеш шляхом індексації, зменшення «bloat» таблиць (VACUUM), і правильного розміру shared_buffers/effective_cache_size. Для lock‑очікувань скоротіть транзакції та усуньте гарячі патерни.

Завдання 8: PostgreSQL — виміряйте коефіцієнт попадання в кеш, але не поклоняйтесь йому

cr0x@server:~$ sudo -u postgres psql -d appdb -c "SELECT datname, blks_hit, blks_read, round(100.0*blks_hit/nullif(blks_hit+blks_read,0),2) AS hit_pct FROM pg_stat_database WHERE datname='appdb';"
 datname | blks_hit | blks_read | hit_pct
---------+----------+-----------+---------
 appdb   | 92000000 |  7800000  | 92.17

Значення: 92% не жахливо, але на VPS з посереднім сховищем ті 8% можуть усе ще давати ваш p99.

Рішення: Якщо ви не можете поліпшити індекси/запити, додайте ОЗП (або зменшіть розмір датасету), щоб підвищити hit rate. Також перевірте sequential scans на великих таблицях.

Завдання 9: PostgreSQL — виявити заборгованість autovacuum і кандидати на bloat

cr0x@server:~$ sudo -u postgres psql -d appdb -c "SELECT relname, n_live_tup, n_dead_tup, last_autovacuum FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 5;"
    relname     | n_live_tup | n_dead_tup |     last_autovacuum
----------------+------------+------------+--------------------------
 events         |    8200000 |    1900000 | 2025-12-28 21:14:09+00
 sessions       |    1500000 |     420000 | 2025-12-28 22:05:51+00
...

Значення: Множина «мертвих» кортежів велика; vacuum відстає. Це збільшує випадкові I/O, шкодить індексам і може спричинити ризик wraparound транзакційних ID, якщо його довго ігнорувати.

Рішення: Налаштуйте autovacuum для окремих таблиць (scale factors, cost limits) і заплануйте вікна для важкого vacuum/analyze, якщо потрібно. На малому VPS «заборгованість vacuum» стає «бюджетною заборгованістю».

Завдання 10: MariaDB — проаналізуйте поведінку innodb buffer pool

cr0x@server:~$ sudo mariadb -e "SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool%';"
+---------------------------------------+-----------+
| Variable_name                         | Value     |
+---------------------------------------+-----------+
| Innodb_buffer_pool_pages_total        | 524288    |
| Innodb_buffer_pool_pages_free         | 1200      |
| Innodb_buffer_pool_read_requests      | 980000000 |
| Innodb_buffer_pool_reads              | 22000000  |
+---------------------------------------+-----------+

Значення: Вільних сторінок мало (pool «повний», нормально). Співвідношення reads до read_requests показує, як часто ви промахуєтесь по кешу. Високий Innodb_buffer_pool_reads на VPS дорогий через затримки сховища.

Рішення: Якщо промахів багато відносно обсягу запитів — збільшіть buffer pool (якщо дозволяє ОЗП) або виправте індекси і зменшіть table scans.

Завдання 11: MariaDB — перевірте тиск на redo log і флашинг

cr0x@server:~$ sudo mariadb -e "SHOW GLOBAL STATUS LIKE 'Innodb_log_waits'; SHOW GLOBAL STATUS LIKE 'Innodb_os_log_fsyncs';"
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Innodb_log_waits | 842   |
+------------------+-------+
+---------------------+--------+
| Variable_name       | Value  |
+---------------------+--------+
| Innodb_os_log_fsyncs| 520000 |
+---------------------+--------+

Значення: Innodb_log_waits > 0 означає, що сесії чекають простору в redo journal або прогресу флашингу — класична вузька пляма записів.

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

Завдання 12: MariaDB — підтвердіть рівень стійкості, який ви фактично запускаєте

cr0x@server:~$ sudo mariadb -e "SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit'; SHOW VARIABLES LIKE 'sync_binlog';"
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| innodb_flush_log_at_trx_commit| 1     |
+-------------------------------+-------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog   | 1     |
+---------------+-------+

Значення: Обидва встановлені в 1 — сильна стійкість (fsync на коміт та fsync бинлогу залежно від конфігурації). Це коштує IOPS, але дає цілісність.

Рішення: Якщо вам потрібна швидкість і ви готові на ризик, можна послабити одне з цих налаштувань. Якщо ви не можете пояснити ризик не‑технічному стейкхолдеру — тримайте їх на 1 і оптимізуйте інші речі.

Завдання 13: Виявити надмірні підключення (PostgreSQL)

cr0x@server:~$ sudo -u postgres psql -d appdb -c "SELECT state, count(*) FROM pg_stat_activity GROUP BY state ORDER BY count(*) DESC;"
 state  | count
--------+-------
 idle   |   320
 active |    25
 null   |     2

Значення: Сотні idle‑підключень витрачають пам’ять і збільшують накладні витрати на управління.

Рішення: Додайте пулер (або виправте пулінг в аплікації). Зменшіть max_connections і примусьте дисципліну. На VPS безпідставні idle‑підключення — розкіш.

Завдання 14: Виявити відставання реплікації (обидві платформи) до того, як воно зруйнує переключення

cr0x@server:~$ sudo mariadb -e "SHOW SLAVE STATUS\G" | egrep 'Seconds_Behind_Master|Slave_IO_Running|Slave_SQL_Running'
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 37

Значення: 37 секунд відставання. Не катастрофа, але при фейловері в інциденті ви обираєте між втратою даних і даунтаймом.

Рішення: Дослідіть сплески записів, повільний диск і довгі транзакції. Розгляньте semi‑sync або кращий диск для реплік, якщо RPO важливий.

Завдання 15: Перевірити біль fsync непрямо (статистика чекпойнтів PostgreSQL)

cr0x@server:~$ sudo -u postgres psql -d appdb -c "SELECT checkpoints_timed, checkpoints_req, round(checkpoint_write_time/1000.0,1) AS write_s, round(checkpoint_sync_time/1000.0,1) AS sync_s FROM pg_stat_bgwriter;"
 checkpoints_timed | checkpoints_req | write_s | sync_s
------------------+-----------------+---------+--------
              120 |              85 |  980.4  |  210.2

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

Рішення: Збільшіть max_wal_size, налаштуйте checkpoint_completion_target і зменшіть бурхливі записи. Якщо можете розділити WAL на кращий том — зробіть це.

Три корпо‑історії зі світу (анонімізовані, правдоподібні, болючі)

1) Інцидент через неправильне припущення: «Більше ОЗП = швидше»

Компанія мала невеликий флот VPS з монолітом і базою даних. БД була MariaDB. Трафік зріс, і команда зробила те, що роблять команди під тиском: подвоїла ОЗП і оголосила перемогу. Графіки виглядали краще приблизно тиждень.

Потім прийшла маркетинг‑кампанія. Затримки підскочили до таймаутів. Апп‑сервери були в порядку. CPU був у нормі. У базі даних було багато пам’яті. Усі дивилися на дашборд, ніби він винен.

Неправильне припущення було простим: «Якщо є вільна пам’ять, база даних має вміти її використати». Вони додали RAM, але зберегли консервативний innodb_buffer_pool_size з ранніх днів, а навантаження змінилося. Читання тепер промахувались по кешу і йшли на диск. Нова RAM переважно стала filesystem cache і «вільною», тоді як база все ще платила за випадкові I/O на шумному сховищі.

Гірше того, був вторинний ефект: більша оперативна пам’ять означала більший потенційний беклог брудних сторінок і більші робочі набори, що зробило сплески ще болючішими, коли flush‑потоки відставали. Коли прийшов піковий трафік, поведінка InnoDB flushing спричинила періодичні паузи, які співпали з піком трафіку.

Вирішення не було героїчним. Вони правильно розміркували buffer pool, перевірили налаштування IO capacity і прогнали replay навантаження, щоб підтвердити стабілізацію p99. Дорога наука: на VPS ОЗП — це лише продуктивність, якщо база налаштована його використовувати.

2) Оптимізація, що відкотилась: «Задвихнемо work_mem»

Інша організація використовувала PostgreSQL на 2 vCPU / 8 GB VPS. Звіти були повільні, і хтось запропонував збільшити work_mem, «щоб сорти робилися в пам’яті». Його підняли агресивно, бо скарг було багато.

День — і звіти летіли. Потім система почала поводитися дивно. Випадкові спайки. autovacuum почав відставати. Ядро почало свопити. Аплікація бачила періодичні 502. Знаєте цей патерн: все виглядає як мережа, коли хост горить.

Відкат був передбачуваний: work_mem — це на операцію, на запит, на бекенд. При конкуренції Postgres лояльно виділяв набагато більше, ніж фізичної пам’яті, і Linux відповів свопінгом. Не легким свопінгом. Тим, що робить VPS схожим на машину з USB‑диском в шухляді.

Вирішення включало зниження work_mem, додавання pooler‑а для обмеження concurency та перепис кількох звітів під попереднє агрегування. Також навчились бенчмаркувати при реалістичній конкуренції. Одноклієнтські бенчмарки — як купувати неправильний сервер.

3) Сумна, але правильна практика, що врятувала день: «Ми тримали vacuum і бекапи нудними»

Маленький SaaS запускав PostgreSQL на скромному VPS з read‑replica. Інфраструктури не було нічого модного, але була дисципліна: autovacuum налаштовано по таблицях з високим churn, а для найгірших були заплановані технічні вікна. Кожна зміна схеми супроводжувалась планом індексів і відкотом.

Одного дня латентність сховища на первинному інстансі погіршилась. Не повний даун — просто достатньо, щоб створити незручності. Чекпойнти займали більше часу, WAL‑флаші повільніли, і затримки аплікації зросли. Команда мала дві переваги: вони знали, що є нормою, і їхня система не несла заборгованості з обслуговування.

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

Інцидент усе ще болів, але не перетворився на багатоденну катастрофу. «Нудна практика» — це не секретний трюк продуктивності. Це просто відмова дозволити базі перетворитися на смітник. На VPS‑бюджетах чистота — це продуктивність.

Поширені помилки: симптом → причина → виправлення

1) Симптом: періодичні 2–10‑секундні спайки латентності

Корінь: чекпойнти (PostgreSQL) або агресивний флашинг (InnoDB), що викликають вибухоподібний синхронний I/O; іноді бекапи конкурують за диск.

Виправлення: Згладьте записи: збільште WAL/redo ємність, налаштуйте частоту чекпойнтів, гарантуйте, що бекапи використовують throttling або запускаються в непіковий час. Підтвердіть через iostat await/%util і статистику bgwriter Postgres.

2) Симптом: «CPU низький, але все повільне»

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

Виправлення: Перевірте iowait, диск чергу і wait events бази. Для блокувань знайдіть блокувальників і скоротіть транзакції.

3) Симптом: Postgres гіршає за дні/тижні без змін коду

Корінь: заборгованість VACUUM/analyze, bloat таблиць/індексів, застарілі статистики планувальника.

Виправлення: Налаштуйте autovacuum (особливо scale factors) для таблиць з високим churn; моніторте dead tuples; плануйте vacuum/analyze; розгляньте партиціювання для даних з високим churn.

4) Симптом: відставання реплікації MariaDB росте під час пікових записів

Корінь: репліка I/O не встигає (redo/binlog fsync‑і, повільний диск), або довгі транзакції затримують apply.

Виправлення: Зменшіть тиск fsync, забезпечте адекватне сховище для репліки, уникайте гігантських транзакцій і моніторьте швидкість apply. Якщо ваш план фейловера розраховує на нуль відставання — припиніть це робити.

5) Симптом: високий load average при помірному CPU

Корінь: черга runnable включає задачі в незмінному I/O‑сні (D‑стан). Load average це враховує.

Виправлення: Підтвердіть через iostat і стани процесів. Виправлення — це сховище, а не більше vCPU.

6) Симптом: раптові OOM kills після «тюнінгу для швидкості»

Корінь: вибух пам’яті на підключення (Postgres work_mem, maintenance_work_mem; MariaDB sort/join buffers) у поєднанні з надмірною кількістю з’єднань.

Виправлення: Впровадьте пулінг, зменшіть max_connections, і встановіть параметри пам’яті, ґрунтуючись на гіршому випадку конкуренції.

7) Симптом: вставки повільні, selects в порядку (PostgreSQL)

Корінь: fsync WAL‑журналу, надмірна кількість індексів або synchronous_commit налаштований не під залізо.

Виправлення: зменшіть кількість індексів, пакуйте записи, налаштуйте WAL/checkpoints, розгляньте async commit лише якщо прийнятно, і переконайтесь, що WAL не конкурує з випадковими читаннями.

8) Симптом: «Ми збільшили інстанс і нічого не змінилось»

Корінь: вузьке місце — сховище або конкуренція; більше CPU/ОЗП цього не змінює.

Виправлення: Спочатку виміряйте iowait, await і lock waits; потім вже витрачайте гроші.

Контрольні списки / покроковий план

A. Вибір рушія для швидкості за гроші (чек‑лист рішення)

  • Потрібні складні SQL, чиста діагностика й передбачувана поведінка? Обирайте PostgreSQL.
  • Переважно простий OLTP, команда знайома з MySQL, гарячий датасет вміщується в buffer pool? MariaDB — хороший варіант з економії.
  • Якість сховища невідома або непостійна? Віддавайте перевагу PostgreSQL, якщо вам потрібна сильніша коректність без спокус «швидко, але ризиковано»; інакше ви загубитеся в налаштуваннях.
  • Висока кількість підключень і аплікація балакуча? PostgreSQL з pooler‑ом; MariaDB теж чутлива, але Postgres пряміше вас покарає.

B. Базова перевірка нового VPS (зробіть перед тим, як звинувачувати БД)

  1. Перевірте steal CPU і затримку сховища в режимі простою і під навантаженням.
  2. Підтвердіть файлову систему, опції монтування і запас вільного місця.
  3. Налаштуйте базові метрики: CPU, iowait, disk await, підключення БД, відставання реплікації.
  4. Запустіть реалістичний бенчмарк з конкуренцією (не один клієнт, не один запит).

C. План налаштування PostgreSQL на VPS (безпечно і ефективно)

  1. Впровадьте пулінг підключень; обмежте активні сесії.
  2. Виставте shared_buffers консервативно; effective_cache_size реалістично.
  3. Встановіть work_mem помірно; перевірте пікову конкуренцію перед збільшенням.
  4. Налаштуйте checkpoint/WAL, щоб зменшити спайки латентності.
  5. Переконайтесь, що autovacuum встигає; налаштуйте per‑table для великих churn таблиць.
  6. Додавайте індекси лише коли вони виправдані; кожен індекс — податок на запис.

D. План налаштування MariaDB на VPS (InnoDB‑перш за все, здоровий глузд)

  1. Розміркуйте innodb_buffer_pool_size під вашу гарячу робочу множину, лишаючи запас для ОС.
  2. Переконайтесь, що є достатня ємність redo; уникайте log waits.
  3. Встановіть innodb_io_capacity згідно з реальністю, а не оптимізмом.
  4. Будьте явними щодо налаштувань стійкості; не «випадково» послаблюйте їх.
  5. Слідкуйте за відставанням реплікації і довжиною історії purge (залежно від версії/інструментів).
  6. Аудит індексів: приберіть ті, що додані «про всяк випадок».

E. Чек‑лист «не купуйте більше ресурсів поки»

  • Ви виявили топ‑запити і виміряли їхній вплив.
  • Підтвердили, чи очікування — це I/O, локи чи CPU.
  • Виключили свопінг і шторми підключень.
  • Згладили поведінку чекпойнтів/флашингу.
  • Переконались, що реплікація і бекапи не конкурують з продукцією.

FAQ

1) Що швидше на дешевому VPS: MariaDB чи PostgreSQL?

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

2) Яке найголовніше вузьке місце на VPS для обох?

Варіативність затримки сховища. Не пропускна здатність — затримка. WAL/redo fsync‑поведінка робить малі паузи видимими для користувачів.

3) Чи варто виносити WAL/redo журнали на окремий диск?

Якщо ваш провайдер VPS пропонує окремий том з незалежними характеристиками продуктивності — так, це може допомогти. Якщо це той самий підкладний пул, ви лише додаєте складність.

4) Чи безпечно послаблювати стійкість заради швидкості?

Іноді. Але «безпечно» — це політика бізнесу, а не налаштування БД. Якщо ви можете допустити втрату останньої секунди транзакцій після аварії — ви можете купити швидкість. Якщо ні — оптимізуйте інші речі.

5) Чому PostgreSQL потребує VACUUM, а MariaDB цього не робить (так помітно)?

MVCC PostgreSQL залишає мертві кортежі до тих пір, поки VACUUM їх не звільнить і не підтримує метадані видимості. InnoDB керує undo/redo і purge інакше. Обидві потребують обслуговування; PostgreSQL просто важче ігнорувати.

6) Як зрозуміти, чи потрібен мені pooler для PostgreSQL?

Якщо у вас сотні переважно неактивних підключень або сплески churn з’єднань — потрібен пулінг. На малому VPS це одне з найкращих «швидкість за гроші» оновлень без купівлі заліза.

7) Які метрики слід оповістити насамперед?

Disk await/%util, iowait, використання swap, активні підключення, відставання реплікації і DB wait events (для Postgres). Оповіщайте про тренди, а не лише пороги.

8) Чи можна налаштуванням компенсувати погане сховище VPS?

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

9) Для швидкості за гроші: масштабувати вертикально чи додати репліку?

Якщо домінують читання — репліка дає більше, ніж вертикальне масштабування. Якщо записів багато і ви обмежені I/O на WAL/redo — вертикальне масштабування (або краще сховище) зазвичай виграє спочатку.

10) Що простіше діагностувати під тиском?

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

Наступні кроки, які ви можете виконати цього тижня

  1. Виміряйте реальність вашого VPS: запустіть mpstat і iostat під час повільного і під час завантаженого періоду. Якщо iowait і await високі — припиніть прикидатися, що вузьке місце це SQL‑синтаксис.
  2. Знайдіть топ‑запити: використайте pg_stat_statements (Postgres) або slow query log / performance schema інструменти (MariaDB) і виправте найгірших порушників спочатку.
  3. Усуньте свопінг: правильно розміркуйте пам’ять і впровадьте пулінг. Свопінг перетворює «дешевий VPS» на «дорогий простій».
  4. Згладьте записи: налаштуйте чекпойнти (Postgres) або флашинг/налаштування логів (MariaDB), щоб зменшити спайки, потім перевірте це по статистиці і графіках затримки.
  5. Зробіть обслуговування нудним: autovacuum (Postgres) і здоров’я InnoDB logs/flush (MariaDB) — це не «пізніші» задачі. Це ваш щомісячний платіж за житло.

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

← Попередня
MySQL vs Redis: Write-through проти Cache-aside — що ламається рідше в реальних застосунках
Наступна →
Дисбаланс vdev у ZFS: чому один повільний vdev тягне весь пул

Залишити коментар