Работал ли ты напрямую с PostgreSQL
Что проверяют
Слово «напрямую» здесь ключевое: спрашивают, писали ли вы SQL руками, а не только дёргали ORM. Хотят понять, представляете ли вы, во что превращается ваш код на стороне базы, умеете ли читать план запроса и управлять транзакциями.
Как отвечать
Скажите, в какой роли вы подходили к базе: писали запросы, проектировали схему, разбирали медленные места. Дальше конкретика по слоям:
- драйвер:
psycopgдля синхронного кода (в старых проектахpsycopg2),asyncpgдля asyncio. Значения всегда через плейсхолдеры драйвера, а не через f-строки; - пул: соединение к PostgreSQL это отдельный процесс на сервере, поэтому пул обязателен, а перед базой часто ставят PgBouncer;
- транзакции: драйвер открывает транзакцию сам,
commitнужен явно, иначе соединение висит в состоянииidle in transaction, держит блокировки и мешает очистке таблиц; - план:
EXPLAIN (ANALYZE, BUFFERS)и умение отличитьSeq ScanотIndex Scan; - схема: индексы под реальные запросы, в том числе составные и частичные, миграции через Alembic или встроенный механизм Django.
Полезно назвать конкретную задачу: ускорили отчёт, разобрали взаимную блокировку, переписали выборку на пакетную. Если опыт только через ORM, так и скажите, но покажите, что видели генерируемый SQL в логах базы.
Где спотыкаются
Склеивают запрос строкой, потому что «параметры всё равно свои». Это инъекция и потеря кэша планов. Плейсхолдер подставляет только значения, имя таблицы или колонки через него не передать, для этого есть отдельный механизм в драйвере.
Тянут результат целиком: fetchall() по большой таблице кладёт процесс по памяти. На таких выборках нужен серверный курсор или чтение пачками.
Путают ORM с базой. Рассказ про Django ORM без единого слова про SQL читается ровно как «напрямую не работал», а вопрос был про это. Вторая беда там же: N+1 запросов, который лечится select_related и prefetch_related, но заметить его можно, только заглянув в лог запросов.