Почему я люблю PostgreSQL

Меня иногда спрашивают: «Ты же инженер баз данных, тебе не всё ли равно, какая СУБД?» Нет. Не всё равно. И если разговор происходит после второй чашки кофе, я могу рассказать об этом дольше, чем кто-либо готов был бы услышать. Так что вот более короткая, письменная версия — без реального ограничения по кофе, но хотя бы с заголовками.

С чего всё началось

Первые пару лет я работала со смесью MySQL и одной проприетарной СУБД, название которой не буду называть из вежливости к бывшим коллегам. Обе работали. Обе решали задачи. Но обе периодически заставляли меня писать код вокруг ограничений движка, а не вокруг задачи: то тихое приведение типов делало сравнение неожиданным, то очередная лицензионная особенность превращала простое масштабирование в разговор с юристами. Когда на одном проекте появился PostgreSQL, первое, что я почувствовала — это что мне наконец не нужно оправдываться перед базой за то, что я хочу написать корректный SQL.

Что зацепило по-настоящему

Не какая-то одна функция, а общее ощущение: PostgreSQL ведёт себя так, будто корректность данных — это не опция, а базовая предпосылка. Строгая типизация, честные транзакции, отсутствие тихих преобразований типов там, где другие движки промолчат и сделают что-то своё. Мне важно, что если я напишу ограничение целостности, оно правда будет соблюдаться, а не будет «рекомендацией», которую можно обойти одной невнимательной вставкой из скрипта миграции.

Маленький, но показательный пример

В PostgreSQL можно повесить CHECK-ограничение прямо на колонку, и оно будет работать всегда, а не только когда об этом вспомнит слой приложения:

ALTER TABLE orders ADD CONSTRAINT positive_amount CHECK (amount > 0);

Расширяемость, о которой не думаешь, пока она не нужна

Второе, что меня удерживает рядом с PostgreSQL много лет — это экосистема расширений. pg_stat_statements для анализа медленных запросов, pg_trgm для нечёткого текстового поиска, JSONB для полуструктурированных данных без необходимости заводить отдельное документное хранилище. Одна база покрывает удивительно много случаев, которые в других экосистемах требовали бы подключения ещё двух-трёх систем — а каждая дополнительная система в проде это ещё один компонент, который может упасть в три часа ночи.

ЗадачаЧто использую в PostgreSQL
Полутекстовый поискtsvector / tsquery, pg_trgm
Гибкие, изменчивые данныеjsonb с GIN-индексами
Аналитика по окнамоконные функции (window functions)
Поиск медленных запросовpg_stat_statements
ГеоданныеPostGIS

Оконные функции — моя тихая любовь

Если бы меня попросили выбрать одну возможность, ради которой стоит остаться с PostgreSQL, я бы назвала оконные функции. Они превращают запросы, которые раньше требовали самосоединений и временных таблиц, в одну читаемую конструкцию:

sql
SELECT customer_id,
       order_date,
       amount,
       SUM(amount) OVER (
         PARTITION BY customer_id
         ORDER BY order_date
       ) AS running_total
FROM orders;

Первый раз, когда я написала что-то подобное и это просто заработало, без временных таблиц и трёх джойнов, я, кажется, вслух сказала «наконец-то» в пустом опенспейсе. Никто не отреагировал — все, видимо, привыкли к таким внезапным победам инженера баз данных.

Открытость и сообщество

Отдельная причина, по которой я остаюсь с PostgreSQL — способ, которым он развивается. Документация подробная и honest: если у функции есть неочевидное поведение на границах, об этом обычно написано прямо там, а не спрятано в комментарии на форуме трёхлетней давности. Список рассылки разработчиков открыт, обсуждения решений видны всем, а не скрыты за закрытой дверью корпоративного roadmap. Когда я нахожу баг или странное поведение, у меня есть реальный шанс прочитать, почему оно так работает, а иногда — и предложить исправление.

Это не значит, что всё идеально

Я не буду делать вид, что у PostgreSQL нет неудобных углов. Репликация и failover исторически требуют больше ручной настройки, чем хотелось бы, хотя с каждым релизом это становится проще. Некоторые операции DDL всё ещё блокируют таблицу дольше, чем можно было бы ожидать. Мониторинг bloat и autovacuum — отдельная дисциплина, а не «поставил и забыл», о чём я уже писала отдельно. Но это осознанные компромиссы движка, который в первую очередь про корректность и предсказуемость, а не про то, чтобы никогда не заставлять администратора думать.

Маленькая история

Была ночь, когда я разбирала проблему с репликацией в 11 вечера, а моя собака решила, что раз я всё равно сижу за столом, самое время положить голову мне на колено и вздохнуть максимально трагично. Реплика в итоге догнала мастер сама, без моего героического вмешательства — оказалось, дело было в сетевой задержке между дата-центрами, которая на утро сама рассосалась. Собака осталась уверена, что это её заслуга, и переубедить её не удалось.

Почему я продолжаю выбирать его снова

Проекты меняются, стек вокруг меняется, а PostgreSQL остаётся частью почти каждого из них — потому что он одинаково хорошо чувствует себя и как простое реляционное хранилище для маленького сервиса, и как ядро для терабайтного кластера с серьёзной аналитической нагрузкой. Мне не нужно каждый раз заново оценивать риски движка — я уже знаю, чего от него ждать в большинстве ситуаций, а любопытные исключения оставляю для этого блога.

Так что да — мне не всё равно, какая СУБД. И если вы дочитали до конца, поздравляю: вы только что выслушали версию этого монолога, сокращённую примерно на два часа и одну чашку кофе.