Что доводилось делать в базе PostgreSQL: вьюшки, процедуры, функции, триггеры, индексы
Что проверяют
Работаете ли вы с PostgreSQL осознанно или через сгенерированный слой, который никогда не открывали. В Go тяжёлой ORM обычно нет, SQL пишется руками, поэтому спрашивают весь набор от вьюшки до индекса и заодно смотрят, как это живёт рядом с пулом соединений и контекстами.
Как отвечать
Идите по сущностям, но с привязкой к своему коду:
- вьюшка: удобна как стабильный контракт для чтения, результат сканируется в структуру обычным
Scan. Права можно выдать на вьюшку, не открывая таблицу целиком; - функция: вызывается прямо в
SELECTи читается черезQueryRow. Процедура только черезCALLвExec, потому что она может коммитить внутри; - триггер: аудит, денормализованные счётчики,
updated_at. Полезная деталь:RETURNINGотдаёт строку уже с правками триггера уровняBEFORE, так что в структуру приедет то, что реально легло в таблицу; - индексы: составной под конкретный
WHEREиORDER BY, частичный под живые строки,GINдляjsonb. Решение принимается поEXPLAIN (ANALYZE, BUFFERS), а не по интуиции; - обвязка: ограничение размера пула,
contextс дедлайном на каждый запрос,COPYвместо цикла вставок, батчи вместо круговых походов в базу.
Где спотыкаются
Пытаются создать индекс без блокировки внутри миграции. Инструменты миграций оборачивают файл в транзакцию, а такому CREATE INDEX транзакция запрещена, и миграция падает на проде. Нужен явный признак «этот файл без транзакции».
Считают, что тысяча горутин ускорит базу. Пул ограничен, лишние запросы стоят в очереди, а без дедлайна в контексте зависший запрос держит соединение до победного. Снаружи это выглядит как «база тормозит», хотя тормозит очередь в приложении.
Уносят логику в процедуры и триггеры как в бесплатное место. Она не видна в репозитории, не проходит ревью, не покрывается тестами, и через полгода никто не понимает, почему поле меняется само. Хороший ответ содержит границу: что живёт в базе и почему именно это.