Выбор между MySQL и PostgreSQL — один из самых частых вопросов при запуске нового проекта. Оба сервера реляционные, распространяются с открытым кодом и выдерживают серьёзные нагрузки. Разница проявляется не в абстрактной «скорости», а в том, какие задачи вы решаете каждый день: короткие транзакции, сложная аналитика, JSON-документы, геоданные или строгие ограничения целостности. Ниже — практическое сравнение с командами для проверки и критериями выбора.
Лицензии и экосистема
MySQL доступен под GPLv2, а для проприетарных сборок Oracle предлагает коммерческую лицензию. MariaDB — совместимый форк под GPLv2, который развивает независимое сообщество. PostgreSQL распространяется под лицензией PostgreSQL License: она разрешает почти любое использование, включая встраивание в закрытый продукт, без отчислений.
Для продукта это важно: PostgreSQL по лицензии проще поставлять вместе с приложением. MySQL и MariaDB разумно выбирать, когда уже есть экспертиза, подходящий managed-сервис или требования совместимости с существующим кодом и популярными CMS.
Типы данных и строгость
PostgreSQL исторически строже. Он не приводит молча строку к числу, поддерживает домены, составные типы, массивы, диапазоны и перечисления. Ошибка в типе всплывает на этапе запроса, а не превращается в неожиданное значение.
MySQL в нестрогом режиме может обрезать строку или подставить значение по умолчанию. В production обязательно проверяйте sql_mode: если в нём нет STRICT_TRANS_TABLES, приложение может терять данные незаметно.
mysql -uroot -p -e "SELECT @@version, @@sql_mode;"
В PostgreSQL базовую проверку удобно делать через psql:
psql -U postgres -c "SHOW server_version;" -c "SHOW standard_conforming_strings;"
Конкурентность и производительность
MySQL использует InnoDB с MVCC и по умолчанию уровнем изоляции REPEATABLE READ. Соединения обслуживаются потоками, поэтому тысячи коротких подключений переносятся легче, чем в PostgreSQL.
PostgreSQL создаёт отдельный процесс на каждое соединение. Это упрощает диагностику, но требует пулера — PgBouncer или Odyssey. Уровень изоляции по умолчанию — READ COMMITTED, для сложных сценариев доступен SERIALIZABLE с проверкой конфликтов.
На практике MySQL часто выигрывает на простых чтениях по первичному ключу, PostgreSQL — на сложных JOIN, оконных функциях, CTE и аналитике. После настройки буферов и индексов разница редко остаётся кратной.
mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
psql -c "SHOW shared_buffers;" -c "SELECT state, count(*) FROM pg_stat_activity GROUP BY state;"
JSON и полнотекстовый поиск
MySQL хранит JSON в бинарном формате и позволяет индексировать отдельные поля через генерируемые колонки. Этого достаточно для логов, настроек и небольших справочников.
PostgreSQL с типом jsonb поддерживает GIN-индексы по документу целиком, операторы вложенности и выборку по структуре. Если JSON — основная модель данных, а не побочный формат, PostgreSQL удобнее и предсказуемее.
CREATE INDEX idx_events_payload ON events USING gin (payload jsonb_path_ops);
SELECT payload->>'user_id' FROM events WHERE payload @> '{"type":"login"}';
Репликация и отказоустойчивость
MySQL применяет бинарный лог, GTID и асинхронную репликацию; автоматическое переключение строят на Group Replication и InnoDB Cluster. PostgreSQL предлагает потоковую физическую репликацию, логическую репликацию и внешние менеджеры вроде Patroni с etcd.
В обеих системах следите за отставанием реплики. В MySQL смотрят Seconds_Behind_Source, в PostgreSQL — pg_stat_replication.
mysql -e "SHOW REPLICA STATUS\G" | grep -E "Running|Behind"
psql -c "SELECT client_addr, state, replay_lag FROM pg_stat_replication;"
Реплика не заменяет резервную копию. Настройте pg_dump, pg_basebackup или XtraBackup и регулярно проверяйте восстановление на отдельном стенде.
Расширения и нестандартные задачи
Экосистема расширений — сильная сторона PostgreSQL: PostGIS для геоданных, pgvector для векторного поиска, TimescaleDB для временных рядов, Citus для шардирования. MySQL даёт встроенные spatial-типы, но такого набора расширений не имеет.
Если проект связан с картами, рекомендациями или аналитикой больших таблиц, это весомый аргумент в пользу PostgreSQL. Для обычного интернет-магазина или блога подобные возможности часто не нужны.
Миграция и совместимость
Перенос с MySQL на PostgreSQL редко бывает механическим. Отличаются регистрозависимость идентификаторов, поведение GROUP BY, функции работы с датами, автоинкремент и синтаксис LIMIT. Помогает утилита pgloader, но схему и запросы всё равно приходится проверять вручную.
pgloader mysql://user:pass@old-db/app postgresql://user:pass@new-db/app
psql -U postgres -d app -c "SELECT count(*) FROM information_schema.tables WHERE table_schema='public';"
Обратный переход встречается реже и обычно связан с требованием заказчика или хостинга. В любом случае сначала переносите тестовую копию, затем сверяйте количество строк и контрольные суммы по ключевым таблицам.
Сопровождение и типичные ловушки
В MySQL следите за размером undo-логов, историей binlog и свободным пространством в табличных пространствах. В PostgreSQL — за autovacuum, раздуванием таблиц и долгими транзакциями, которые удерживают старые версии строк.
psql -c "SELECT relname, n_dead_tup FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 5;"
psql -c "SELECT pid, now()-xact_start FROM pg_stat_activity WHERE xact_start IS NOT NULL ORDER BY 2 DESC;"
Для MySQL полезна проверка фрагментации и свободного места:
mysql -e "SELECT table_name, data_free FROM information_schema.tables WHERE table_schema='app' ORDER BY data_free DESC LIMIT 5;"
Не запускайте массовые изменения схемы в часы пик. В PostgreSQL используйте lock_timeout и CREATE INDEX CONCURRENTLY, в MySQL — online DDL и проверку плана на копии базы.
Когда что выбирать
- MySQL или MariaDB: типовой веб-проект с большим числом коротких запросов, готовый managed-сервис, команда с опытом MySQL, совместимость с популярными CMS.
- PostgreSQL: сложная предметная модель, отчёты, JSON-документы, геоданные, векторный поиск, строгие ограничения целостности и расширения.
- Не выбирайте по чужому бенчмарку: прогоните свои запросы на своём объёме данных.
Чек-лист перед стартом
- Оцените соотношение чтений и записей и средний размер транзакции.
- Проверьте, есть ли в команде экспертиза по конкретной СУБД.
- Уточните требования к репликации, RPO и RTO.
- Прогоните репрезентативные запросы через sysbench или pgbench.
- Заложите мониторинг, резервное копирование и план обновлений.
- Убедитесь, что выбранная ветка получает обновления безопасности.
Итог
Универсального победителя нет. MySQL остаётся прагматичным выбором для простых высоконагруженных веб-приложений и проектов, где важна совместимость. PostgreSQL лучше подходит для систем со сложной логикой, аналитикой и нестандартными типами данных. Решение принимайте по модели данных, нагрузке и компетенциям команды.