·2 хв читання·fluxLab.dev

Уроки продуктивності PostgreSQL з досвіду 6 SaaS-продуктів

Реальні техніки оптимізації PostgreSQL, отримані з експлуатації шести продакшн SaaS-баз даних у fluxLab.dev — індексація, тюнінг запитів та пулінг зєднань.

PostgreSQLПродуктивністьБази данихSaaS

Вступ

Кожен SaaS-продукт fluxLab.dev працює на PostgreSQL. Через наші продукти та 46 000+ користувачів ми накопичили практичні знання про те, що робить PostgreSQL швидким — і що робить його повільним.

Урок 1: Індекси не безкоштовні

Інстинкт «просто додай індекс» швидко шкодить. Кожен індекс уповільнює запис та споживає пам'ять. Ми додаємо індекси лише для реальних патернів запитів, перевірених через EXPLAIN ANALYZE.

Часткові індекси особливо потужні. У Jobber більшість запитів фільтрують за user_id та status = 'active'. Частковий індекс лише на активних записах менший та швидший за повний.

Ми видалили 12 непотрібних індексів по наших базах і побачили покращення швидкості запису на 15%.

Урок 2: N+1 запити ховаються в ORM

Ми перестали використовувати ORM після третього продукту. З чистим SQL та pgx у Go кожен запит видимий та обґрунтований. Один запит з JOIN замість чотирьох окремих запитів — час відповіді зменшився з 120мс до 8мс.

Урок 3: Пулінг з'єднань важливіший, ніж здається

PostgreSQL створює новий процес ОС для кожного з'єднання. Ми використовуємо pgxpool з ретельно налаштованими параметрами: 25 максимальних з'єднань на інстанс сервісу. Для наших серверів Hetzner Cloud з 4ГБ RAM це оптимальна точка.

Урок 4: Використовуй EXPLAIN ANALYZE, а не EXPLAIN

EXPLAIN показує план запиту. EXPLAIN ANALYZE фактично виконує запит і показує реальний час. Різниця важлива, бо оцінки PostgreSQL можуть бути неточними. Ми запускаємо EXPLAIN ANALYZE на кожному запиті, що займає більше 50мс у логах продакшну.

Урок 5: Timestamp-колонки потребують часових поясів

Ми це засвоїли на гіркому досвіді з WashFlow. Використовуйте TIMESTAMPTZ, а не TIMESTAMP. Зберігайте все в UTC. Конвертуйте в локальний час лише на фронтенді.

Урок 6: М'яке видалення створює складність запитів

Ми спробували soft delete у нашому продукті Accounting. Кожен запит потребував WHERE deleted_at IS NULL, і ми пропустили це в кількох місцях. Тепер ми надаємо перевагу hard delete з правильними foreign key constraints та окремою таблицею аудиту.

Урок 7: Міграції повинні бути зворотними

Кожна міграція у fluxLab.dev має скрипти up та down. Ми тестуємо відкати в стейджингу перед деплоєм на продакшн.

Висновок

PostgreSQL надзвичайно здатний з коробки. Більшість проблем продуктивності спричинені нашими власними помилками. Найкраща оптимізація — писати правильні запити з самого початку та вимірювати все через EXPLAIN ANALYZE.