| Параметр | Postgresql | Mysql |
|---|---|---|
| Оконные функции | Есть с версии 8.4 (2009), полный набор: RANK, LEAD/LAG, FILTER, рамки RANGE/ROWS | Появились только в MySQL 8.0 (2018); до этого эмулировались через переменные @ |
| CTE и рекурсия | WITH и WITH RECURSIVE с версии 8.4; поддержка материализации | CTE и рекурсивные CTE только с 8.0 |
| Работа с JSON | Типы json и jsonb (бинарный, индексируемый через GIN), богатый набор операторов | Тип JSON есть с 5.7, но без бинарного индексируемого варианта и с более скромным API |
| Система типов | Массивы, ENUM, диапазоны, гео (PostGIS), UUID, hstore, пользовательские типы | Базовый набор + ENUM и SET; массивов и диапазонов нет |
| Расширяемость | Расширения (CREATE EXTENSION), свои типы, операторы, языки (PL/pgSQL, PL/Python) | Плагины хранилищ и UDF, но экосистема расширений заметно уже |
| Регистр строк по умолчанию | Сравнение строк регистрозависимое (case-sensitive) | По умолчанию collation ci — сравнение регистронезависимое |
| Деление целых | 5/2 = 2 (целочисленное); для дроби нужен явный cast | 5/2 = 2.5 (возвращает дробь по умолчанию) |
| Транзакции и DDL | Транзакционный DDL: ALTER/CREATE можно откатить в транзакции | DDL обычно вызывает неявный commit; откатить нельзя |
| Профиль производительности | Сильнее на сложных JOIN, аналитике, параллельных планах и конкурентной записи (MVCC) | Традиционно быстр на простых чтениях и высокой нагрузке простых запросов |
| Диалект и удобство | RETURNING, DISTINCT ON, generate_series, ::cast, богатые агрегаты | Проще синтаксис, но меньше аналитических конструкций; есть свои функции дат |
| Экосистема и стоимость | Полностью open-source (лицензия PostgreSQL), нет коммерческого владельца | Open-source (GPL) под управлением Oracle; есть форк MariaDB |
PostgreSQL поддерживает оконные функции с версии 8.4 (2009), а MySQL получил их только в 8.0 (2018). До этого в MySQL их эмулировали через пользовательские переменные (@row := ...), что было хрупко и плохо читалось. Поэтому в старых MySQL-проектах RANK, ROW_NUMBER и LAG/LEAD часто отсутствуют — это частый вопрос на собеседовании.
В PostgreSQL деление двух целых чисел возвращает целое: 5/2 = 2, и для дробного результата нужен явный cast, например 5::numeric/2. В MySQL 5/2 по умолчанию вернёт 2.5. Об этом легко споткнуться при расчёте конверсий и долей — всегда приводите тип явно.
В PostgreSQL json хранит текст как есть, а jsonb — бинарное представление, которое быстрее читается, поддерживает индексы GIN и операторы поиска. В MySQL есть тип JSON с 5.7, но без разделения на текст/бинарь и с более скромным набором функций. Для аналитики полуструктурированных данных PostgreSQL с jsonb обычно удобнее.
Знать нужно сам SQL, а не конкретную СУБД — базовые SELECT, JOIN, GROUP BY, оконные функции переносимы. Но PostgreSQL чаще встречается в дата-командах и богаче на аналитические конструкции, поэтому его стоит освоить в первую очередь и помнить о диалектных различиях. Потренироваться на реальных задачах и вопросах с собеседований можно в /sql-sandbox и в разделе /interviews.
Postgresql vs Clickhouse · Pandas vs Polars · Tableau vs Powerbi Datalens Superset · SQL vs Pandas · Dbt vs Airflow · Redshift vs Bigquery vs Snowflake · Airflow vs Dagster vs Prefect · Greenplum vs Clickhouse · Excel vs SQL · Sqlite vs Postgresql · Spark vs Pandas · Power Bi vs Excel · Clickhouse vs Druid · Python vs R