Чему меня научили ORM: просто выучи SQL
Автор, работавший 30 месяцев с Postgres и SQLite, преимущественно используя SQLAlchemy и Hibernate, пришел к выводу, что ORM больше вредят, чем помогают. Хотя ORM могут дополнять работу с SQL, они не должны её заменять.
Основные проблемы, с которыми он столкнулся: расползание атрибутов в таблицах (когда один объект требует 600+ атрибутов и 14 соединений для загрузки), необходимость писать сложные запросы через ORM вместо прямого SQL, дублирование схемы данных (в базе и в приложении), сложности с управлением идентичностью объектов, проблемы с транзакциями и их контекстным управлением.
Автор переосмыслил подход: вместо того, чтобы думать об объектах приложения как о чём-то, что нужно сохранить в базе (назначение ORM), он начал думать о базе как о сложном типе данных с API, запросами, которые возвращают типизированные результаты. Решение: использовать шаблонные SQL-запросы, описывая таблицы через ORM. Вывод: если для эффективной работы нужно понимать SQL, проще использовать SQL напрямую, чем гадать, как ORM его транслирует.
Ключевые факты
- ORM требуют глубокого знания SQL несмотря на свою идею упростить разработку
- Расползание атрибутов и множество foreign key создают неэффективные запросы и нагрузку на переводе строк БД в объекты
- Для сложных случаев (window functions, оптимизация) проще написать SQL напрямую, чем заставлять ORM сгенерировать эффективный запрос
- Дублирование схемы между БД и приложением, неизбежная сложность, которую ORM не решают
- Лучший подход: воспринимать БД как типизированный API с запросами вместо попытки отображать объекты на таблицы
Почему это важно
После 2.5 лет рабочего опыта автор столкнулся с рядом проблем ORM, которые заставили пересмотреть весь подход. Практический опыт показал, что ORM не решают основные сложности взаимодействия объектно-ориентированных языков и реляционных баз данных. Наоборот, они добавляют новые уровни абстракции, которые требуют понимания их внутреннего устройства, а значит, и понимания SQL, который они якобы должны скрывать.
Кому это важно
Разработчикам на Python, Java и других языках, работающим с ORM вроде SQLAlchemy, Hibernate, Django ORM и подобными. Особенно тем, кто сталкивается с производительностью, сложными схемами данных или системами, ориентированными на события (вроде обработки timeline). Аргумент также релевантен для архитекторов систем, выбирающих технологический стек и инструменты работы с БД.
Как это применить
Вместо полной замены SQL на ORM, использовать гибридный подход: ORM для удобства описания схемы таблиц, но писать сложные запросы на чистом SQL или через шаблонизацию SQL. Перестать думать об объектах приложения как о том, что нужно сохранить в БД, а начать думать о БД как о типизированном источнике данных, доступном через API запросов. Инвестировать в изучение SQL и оптимизацию запросов как основных инструментов, а не обёрток вроде ORM.
Можно ли доверять
Статья опубликована в 2014 году опытным разработчиком на основе практического опыта, а не теории. Выводы подкреплены конкретными примерами: таблицы с 600+ атрибутами и 14 соединениями, оптимизация запроса с минут до секунд путём добавления проекции. Хотя текст имеет субъективный характер (автор подчёркивает «для меня»), сама критика ORM хорошо известна и задокументирована в IT-сообществе, это не новая идея, а обоснованная практикой переоценка выбора инструмента.
Риски и подводные камни
Полный отказ от ORM может привести к дублированию логики в SQL и коде приложения. Автор признаёт, что его подход может не подходить для всех проектов, он специфичен для его use case с событийным хранилищем и отчётностью. Переход на чистый SQL требует высокого уровня знаний, может замедлить разработку в коротких проектах, и повышает роль баз данных в архитектуре. Также автор задумывается о хранимых процедурах (stored procedures), которые традиционно избегаются разработчиками, но это может создать новые проблемы в интеграции и контроле версий.
«Если вам нужно знать SQL, просто используйте SQL, так как это предотвращает необходимость знать, как преобразование не-SQL кода в SQL происходит.»
— Steven Wozniak (автор блога)