Антон Ларичев

Введение
Выбор между PostgreSQL и MySQL — один из первых архитектурных вопросов при старте нового проекта. Обе системы зрелые, проверены в продакшне и поддерживаются крупными облачными провайдерами. Но у каждой свои сильные стороны, и неправильный выбор способен создать технический долг на годы вперёд.
В этой статье разберём ключевые различия на практических примерах: типы данных, транзакции, репликация, производительность и экосистема.
Архитектура и лицензия
MySQL изначально создавался как быстрая и простая СУБД для веб-приложений. PostgreSQL с самого начала проектировался как объектно-реляционная система с упором на стандарты SQL и расширяемость.
MySQL распространяется под двойной лицензией: GPL и коммерческой от Oracle. PostgreSQL — под собственной лицензией, максимально близкой к MIT, без каких-либо ограничений на коммерческое использование.
Типы данных
PostgreSQL поддерживает значительно более широкий набор встроенных типов.
-- PostgreSQL: нативный JSON с индексацией
CREATE TABLE events (
id SERIAL PRIMARY KEY,
payload JSONB NOT NULL, -- бинарный JSON, поддерживает GIN-индексы
tags TEXT[], -- нативный массив
period TSRANGE -- диапазон временных меток
);
-- Запрос по полю внутри JSONB
SELECT * FROM events
WHERE payload @> '{"type": "purchase"}';
-- MySQL: JSON поддерживается с версии 5.7, но без GIN-индексов
CREATE TABLE events (
id INT AUTO_INCREMENT PRIMARY KEY,
payload JSON NOT NULL
);
-- Генерируемая колонка для индексации поля из JSON
ALTER TABLE events
ADD COLUMN event_type VARCHAR(50)
GENERATED ALWAYS AS (payload->>'$.type') STORED,
ADD INDEX idx_event_type (event_type);
PostgreSQL также поддерживает: UUID, HSTORE, INET, CIDR, геометрические типы, пользовательские перечисления (ENUM как полноценный тип), составные типы и домены.
Транзакции и MVCC
Оба движка используют MVCC (Multi-Version Concurrency Control), но реализуют его по-разному.
MySQL (InnoDB) хранит старые версии строк в отдельном сегменте — undo log. PostgreSQL хранит все версии прямо в основном файле таблицы и периодически очищает их через VACUUM.
-- PostgreSQL: DDL внутри транзакции (MySQL так не умеет)
BEGIN;
ALTER TABLE orders ADD COLUMN discount NUMERIC(5,2) DEFAULT 0;
UPDATE orders SET discount = 5.0 WHERE total > 10000;
COMMIT; -- или ROLLBACK — схема откатится вместе с данными
-- MySQL: DDL вызывает неявный COMMIT
BEGIN;
ALTER TABLE orders ADD COLUMN discount DECIMAL(5,2) DEFAULT 0;
-- здесь транзакция уже зафиксирована, откат невозможен
UPDATE orders SET discount = 5.0 WHERE total > 10000;
COMMIT;
PostgreSQL поддерживает все четыре уровня изоляции стандарта SQL, включая настоящий SERIALIZABLE через SSI (Serializable Snapshot Isolation) без блокировок на чтение.
Производительность
MySQL традиционно быстрее на простых операциях чтения и хорошо масштабируется в сценариях с высоким количеством коротких транзакций (например, интернет-магазины, OLTP-нагрузка с простой схемой).
PostgreSQL показывает преимущество на сложных аналитических запросах, запросах с оконными функциями и при работе с JSONB.
-- PostgreSQL: оконные функции — нативная поддержка
SELECT
user_id,
order_date,
total,
SUM(total) OVER (PARTITION BY user_id ORDER BY order_date) AS running_total,
RANK() OVER (PARTITION BY user_id ORDER BY total DESC) AS rank_by_amount
FROM orders;
-- MySQL: оконные функции поддерживаются с версии 8.0
SELECT
user_id,
order_date,
total,
SUM(total) OVER (PARTITION BY user_id ORDER BY order_date) AS running_total
FROM orders;
Репликация и масштабирование
MySQL предлагает зрелую и хорошо документированную потоковую репликацию (binlog), которую легко настроить. Существуют решения для multi-master репликации (Galera Cluster, Group Replication).
PostgreSQL поддерживает физическую (streaming) и логическую репликацию. Логическая репликация позволяет реплицировать отдельные таблицы и публикации, что удобно при миграциях.
-- PostgreSQL: создание публикации для логической репликации
CREATE PUBLICATION orders_pub FOR TABLE orders, order_items;
-- На реплике
CREATE SUBSCRIPTION orders_sub
CONNECTION 'host=primary dbname=shop user=replicator'
PUBLICATION orders_pub;
Расширения PostgreSQL
Одно из главных преимуществ PostgreSQL — богатая экосистема расширений:
-- PostGIS: геопространственные данные
CREATE EXTENSION postgis;
SELECT name, ST_Distance(
location::geography,
ST_MakePoint(37.6173, 55.7558)::geography -- координаты Москвы
) AS distance_meters
FROM shops
ORDER BY distance_meters
LIMIT 10;
-- pg_trgm: нечёткий поиск по строкам
CREATE EXTENSION pg_trgm;
CREATE INDEX idx_title_trgm ON articles USING GIN (title gin_trgm_ops);
SELECT title, similarity(title, 'postresql') AS sim
FROM articles
WHERE title % 'postresql' -- найдёт "postgresql" несмотря на опечатку
ORDER BY sim DESC;
Частые ошибки
Выбор MySQL «по привычке». Многие разработчики выбирают MySQL, потому что встречали его в туториалах. Если проект предполагает сложную аналитику, JSON-документы или геоданные — PostgreSQL окупит время на изучение.
Игнорирование VACUUM в PostgreSQL. PostgreSQL не удаляет старые версии строк автоматически при каждом обновлении. Если autovacuum отключён или настроен неверно, таблицы начнут раздуваться. Проверяйте параметры autovacuum_vacuum_scale_factor и autovacuum_analyze_scale_factor под нагрузку.
Charset utf8 вместо utf8mb4 в MySQL. Тип utf8 в MySQL — это не настоящий UTF-8, он поддерживает только символы до U+FFFF. Для хранения emoji и символов за пределами BMP всегда используйте utf8mb4.
-- MySQL: правильное создание таблицы с поддержкой emoji
CREATE TABLE comments (
id INT AUTO_INCREMENT PRIMARY KEY,
body TEXT NOT NULL
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Отсутствие индексов на внешние ключи в MySQL. В отличие от PostgreSQL, MySQL не создаёт индекс по внешнему ключу автоматически при использовании MyISAM (для InnoDB — создаёт). Всегда проверяйте план запроса через EXPLAIN.
Заключение
Выбирайте MySQL, если проект — высоконагруженный OLTP с простой схемой, команда хорошо знает MySQL, или проект работает на управляемых сервисах вроде Amazon Aurora.
Выбирайте PostgreSQL, если нужны: сложные запросы, JSONB, геоданные, транзакционный DDL, строгое соответствие стандартам SQL или расширения типа PostGIS, TimescaleDB, pgvector.
В большинстве новых проектов PostgreSQL — более универсальный выбор: он не уступает MySQL в скорости базовых операций и при этом не ограничивает вас в будущем, когда требования усложнятся.






Комментарии
0