Миграции ORM. Мы все на них сильно опирались, верно? Prisma, Drizzle — обещают лёгкий переход от кода к базе, без головной боли с SQL. Но на прошлой неделе один разработчик угробил четыре часа на медленный API, а виновник оказался предсказуемым: внешний ключ без индекса. Шок.
Все ждали чуда. Подключили отношения в TypeScript, запустили миграцию — и готово. Связь Users с Orders? Само собой. Производительность? Их забота, не ваша. Только теперь это проблема всех, когда таблицы разрастаются до миллионов строк, а запросы ползут как на диалапе.
Дело старое. Ещё в 2005-м разработчики Hibernate попадали в ту же ловушку. ORM абстрагировали боль, да, но ценой невидимых узких мест. История повторяется: создатели инструментов ставят скорость разработки выше реальности базы. А кто наживается? Те же ORM-компании с глянцевыми доками и платными корпоративными апгрейдами, пока ваши облачные счета взлетают.
Я потратил 4 часа на прошлой неделе, отлаживая медленный эндпоинт API. Виновник? Отсутствующий индекс на внешнем ключе, который мой ORM “доброжелательно” спрятал во время миграции схемы.
В точку. ORM добавляют ограничение внешнего ключа — ALTER TABLE “orders” ADD CONSTRAINT “fk_user” FOREIGN KEY (“user_id”) REFERENCES “users”(“id”); — но забывают про CREATE INDEX “idx_orders_user_id” ON “orders”(“user_id”);. Почему? Мол, индексация — это ‘деталь реализации’. Чушь. Без неё Postgres последовательно сканирует всю таблицу Orders при каждом запросе по пользователю. Нормально на 1K строк. Катастрофа на 10M.
Разработчики смотрят на schema.ts, а не на реальную базу. Связи? Закопаны в коде. Нет визуальной карты. Нет предупреждений. Чёрный ящик в полной готовности.
Почему миграции ORM вечно пропускают индексы?
Ленивые дефолты, вот почему. Движок миграций Prisma рассчитывает, что вы оптимизируете потом — или вообще не заметите. У Drizzle та же песня. Они генерируют ограничение для целостности данных, а индексы — на вашей совести. Как шоссе без обочины: вроде безопасно, пока пробки не начались.
А в пресс-релизах? ‘Декларативное управление схемой!’ Мило. Но это скрывает реальность отношений. Хребет вашего приложения — таблицы, джойны, сканирования — растворяется в JS-файлах. Я видел команды, которые выкатывали в прод, радовались быстрым деплоям, а потом latency подскакивал в 100 раз. Кто-то удивлён?
Моё особое мнение: это эхо краха хайпа вокруг NoSQL в 2012-м. Все бросили реляционные БД ради ‘масштаба прежде всего’, потеряли ACID, потом раскаялись. ORM — реляционная версия того же: масштабируй потом, молись сильнее.
Тут и вступает Tiger SQL. Open-source визуализатор Postgres в браузере. Вставьте схему или подключите базу — и вуаля: ERD с отображёнными связями. ИИ подсвечивает пропущенные индексы, медленные запросы. Без лишнего, без платных стен. Форкните на GitHub.
Меняет ли это расклад? Немного. Это пластырь на лень ORM. Но чёрт, как же он упрощает аудит схем. Запускайте локально, ловите дыры до взрыва в проде.
Спасёт ли Tiger SQL вашу команду от ORM-ада?
Возможно. Бесплатный, лёгкий — работает в браузере. Визуальные ERD? Мгновенно. Оптимизация на ИИ? Предупреждает о пропущенных B-Tree индексах, неиспользуемых колонках, даже планах запросов. Никакого vendor lock.
Но давайте без иллюзий. Такие инструменты вылезают ежегодно. DbSchema, расширения pgAdmin — обещают то же самое. Преимущество Tiger? ИИ-ум без счёта от OpenAI плюс чистота open source. Никто тут не рубит бабла; это чесалка для разработчика.
Проверил сам. Скинул схему из Prisma: ERD высветил user_id без индекса. Предложил фиксы за секунды. Вот в чём выигрыш — возвращает видимость, которую ORM украли.
Сомневаетесь? Форкните, запустите, убедитесь. Или держитесь за миграции на веру и платите за производительность.
Как вычислить пропущенные индексы без крутых инструментов
Не ждите. Запускайте EXPLAIN ANALYZE на запросах. Seq Scan по внешним ключам? Красный флаг. Потом:
SELECT schemaname, tablename, indexname, idx_scan
FROM pg_stat_user_indexes
WHERE idx_scan < 1