Postgres extensions для аналитики на собеседовании Data Engineer

Проверь себя · 1/3разбор после ответа
Какое утверждение про RIGHT JOIN верно в аналитических запросах?

Зачем DE знать расширения Postgres

Postgres редко используют «голым». Его сила — в расширениях: одной командой CREATE EXTENSION база превращается то в аналитическое хранилище с быстрым поиском по запросам, то в time-series движок, то в векторную БД для RAG. Для Data Engineer это удобно тем, что не нужно тащить в стек ещё один сервис ради одной задачи — часто хватает расширения поверх уже работающего Postgres.

На собесе про расширения спрашивают не «перечисли пять штук», а прикладно: «запрос в проде тормозит — как найдёшь виновника?», «таблица распухла после массовых удалений, как почистить без простоя?», «нужен семантический поиск по эмбеддингам — куда положишь векторы?». За каждым таким вопросом стоит конкретное расширение. Ниже — шесть, которые чаще всего всплывают на собеседовании DE, с разбором, что это, когда применять и на чём валятся кандидаты.

pg_stat_statements

pg_stat_statements — стандартное расширение, которое собирает статистику выполнения всех запросов к базе: сколько раз запрос вызывался, суммарное и среднее время, количество прочитанных блоков. Запросы при этом нормализуются — литералы заменяются на плейсхолдеры, поэтому WHERE id = 1 и WHERE id = 2 считаются одним запросом. Это главный инструмент DE, когда нужно понять, что нагружает базу.

CREATE EXTENSION pg_stat_statements;

-- Топ-10 запросов по суммарному времени выполнения
SELECT query, calls, mean_exec_time, total_exec_time
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

Важный нюанс: расширение нужно заранее прописать в shared_preload_libraries и перезапустить Postgres — просто CREATE EXTENSION в рантайме не включит сбор.

На собесе типичный вопрос — «как найдёшь медленный запрос в проде?». Правильный ответ: смотреть pg_stat_statements, отсортированный по total_exec_time, а не по mean_exec_time. Быстрый запрос, вызываемый миллион раз в минуту, нагружает базу сильнее, чем один тяжёлый отчёт раз в час, хотя среднее время у него мизерное. Именно суммарное время показывает, куда реально уходят ресурсы.

pg_repack

pg_repack — расширение для перестройки таблиц и индексов без блокировки на запись. После активных UPDATE и DELETE таблица «распухает» (bloat): из-за MVCC мёртвые версии строк занимают место, пока их не соберёт autovacuum. Классический способ ужать таблицу — VACUUM FULL, но он берёт эксклюзивную блокировку и таблица недоступна на всё время операции. На проде это неприемлемо.

pg_repack -t my_table -d my_db

pg_repack работает иначе: он создаёт копию таблицы, через триггеры доливает в неё изменения, накопившиеся за время работы, и в самом конце атомарно подменяет старую таблицу новой. Эксклюзивная блокировка нужна только на короткий момент этой подмены. Платить за это приходится дисковым местом — на время операции нужна примерно двойная копия таблицы.

На собесе часто спрашивают разницу между VACUUM, VACUUM FULL и pg_repack: обычный VACUUM помечает мёртвые строки как переиспользуемые, но не возвращает место ОС и не блокирует; VACUUM FULL возвращает место, но с полной блокировкой; pg_repack возвращает место почти без блокировки, но требует свободного диска.

TimescaleDB

TimescaleDB — расширение, превращающее Postgres в полноценную time-series СУБД, сохраняя при этом обычный SQL. Оно даёт три ключевые вещи для работы с временными рядами.

Hypertables — таблицы с автоматическим партиционированием по времени. Снаружи это одна таблица, внутри — набор чанков (chunks) по интервалам, что резко ускоряет запросы за период и упрощает удаление старых данных.

SELECT create_hypertable('events', 'event_time', chunk_time_interval => INTERVAL '1 day');

Continuous aggregates — материализованные представления, которые инкрементально досчитываются по мере поступления данных, а не пересчитываются целиком. Удобно для дашбордов с почасовыми и посуточными агрегатами.

Компрессия — старые чанки сжимаются, часто на 90%+, потому что колоночное сжатие хорошо работает на однородных временных данных.

Подходит для метрик, IoT-телеметрии и финансовых тиков. По задачам сравним с InfluxDB, но выигрывает тем, что остаётся Postgres: полноценные JOIN, оконные функции и привычный SQL никуда не деваются.

pgvector

pgvector — расширение, добавляющее в Postgres тип vector и поиск по векторной близости. Это основа для семантического поиска, рекомендаций и RAG: тексты и картинки превращают в эмбеддинги (векторы), а затем ищут ближайшие по косинусной или евклидовой метрике.

CREATE EXTENSION vector;
CREATE TABLE items (id BIGSERIAL, embedding VECTOR(768));
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);

-- 10 ближайших векторов к заданному
SELECT * FROM items ORDER BY embedding <=> '[...]' LIMIT 10;

Оператор <=> считает косинусное расстояние, а индекс HNSW (есть ещё IVFFlat) даёт приближённый, но быстрый поиск ближайших соседей — без него запрос честно перебирает всю таблицу. Главный плюс pgvector в том, что векторы лежат рядом с остальными данными: можно фильтровать обычным WHERE (по категории, дате, пользователю) в том же запросе, что и векторный поиск.

Подходит для небольших и средних объёмов — до единиц-десятков миллионов векторов. На собесе стоит честно проговорить границу: под сотни миллионов векторов и высокий QPS чаще берут специализированные векторные БД (Qdrant, Milvus), но для большинства продуктовых задач pgvector закрывает вопрос без отдельного сервиса.

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

PostGIS

PostGIS — расширение для геоданных, фактический индустриальный стандарт. Оно добавляет типы geometry и geography, сотни пространственных функций и пространственные индексы на базе GiST — всё, что нужно для работы с координатами, зонами доставки и поиском «что рядом».

CREATE EXTENSION postgis;

-- Места в радиусе 5 км от точки
SELECT name FROM places
WHERE ST_DWithin(location::geography, ST_MakePoint(37.6, 55.7)::geography, 5000);

Здесь важный нюанс, на котором ловят на собесе: у типа geometry расстояния считаются в градусах координат, а не в метрах, поэтому для честного радиуса в метрах координаты приводят к типу geography и используют ST_DWithin — он к тому же умеет опираться на пространственный индекс, в отличие от простого сравнения ST_Distance(...) < 5000. Спросить про разницу geometry и geography и про то, использует ли запрос индекс, — классика геосекции.

hll

hll — расширение, реализующее алгоритм HyperLogLog для приблизительного подсчёта уникальных значений. Точный COUNT(DISTINCT ...) на миллиардах строк требует много памяти, потому что нужно держать все уникальные значения. HyperLogLog жертвует точностью (типичная погрешность около 2%) ради фиксированного и очень маленького объёма памяти.

CREATE EXTENSION hll;

CREATE TABLE daily_active (day DATE, users HLL);
INSERT INTO daily_active VALUES (...);

-- Уникальные пользователи по дням
SELECT day, hll_cardinality(users) AS unique_users FROM daily_active;

Главная фишка, ради которой его берут, — HLL-структуры складываются (union) без потери смысла. Можно хранить по одному HLL на каждый день, а месячных уникалов получить объединением дневных структур — не пересчитывая заново по сырым логам. Это позволяет строить «уникальные пользователи за любой период» дёшево и быстро. На собесе именно это свойство мерджабельности и стоит назвать, когда спрашивают, зачем нужен HLL вместо обычного COUNT(DISTINCT).

Частые ошибки

  • Сортировать pg_stat_statements по mean_exec_time. Так теряется главный источник нагрузки — дешёвый запрос, вызываемый миллионы раз. Смотреть надо на total_exec_time.
  • Гонять VACUUM FULL на проде. Полная блокировка таблицы кладёт сервис. Для очистки bloat под нагрузкой берут pg_repack.
  • Считать pgvector заменой любому векторному поиску. Он отлично работает до десятков миллионов векторов, но под огромный масштаб и высокий QPS нужна специализированная БД.
  • Мерить расстояние в PostGIS по типу geometry. В geometry расстояние в градусах, а не в метрах. Для метров — geography и ST_DWithin.
  • Ждать точный ответ от hll. HyperLogLog приблизительный (около 2% погрешности). Для биллинга и финансов, где нужна точность, он не подходит.

Связанные темы

FAQ

Как найти медленный запрос в Postgres на собесе?

Через pg_stat_statements, отсортировав запросы по total_exec_time. Именно суммарное время показывает реальную нагрузку: частый дешёвый запрос грузит базу сильнее редкого тяжёлого. Расширение нужно заранее включить через shared_preload_libraries.

Чем pg_repack лучше VACUUM FULL?

VACUUM FULL возвращает место ОС, но берёт эксклюзивную блокировку — таблица недоступна всё время операции. pg_repack делает то же самое почти без блокировки: строит копию, доливает изменения через триггеры и атомарно подменяет таблицу. Ценой служит временно удвоенный объём на диске.

Когда брать pgvector, а когда отдельную векторную БД?

pgvector хорош, когда векторов до десятков миллионов и хочется хранить их рядом с реляционными данными, фильтруя обычным WHERE. Под сотни миллионов векторов и высокий QPS берут специализированные решения вроде Qdrant или Milvus.

Зачем нужен hll, если есть COUNT(DISTINCT)?

COUNT(DISTINCT) точный, но дорогой по памяти на больших объёмах. HyperLogLog считает уникалов приблизительно (около 2% ошибки) при крошечном фиксированном объёме, а его структуры можно складывать — из дневных HLL получить месячных уникалов без пересчёта по сырым данным.

Это официальная информация?

Нет. Статья основана на документации Postgres и его расширений и на опыте кандидатов. Набор расширений и глубина вопросов зависят от компании и команды.


Тренируйте Data Engineering — откройте тренажёр с 1500+ вопросами для собесов.