Postgres extensions для аналитики на собеседовании Data Engineer
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_dbpg_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 закрывает вопрос без отдельного сервиса.
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% погрешности). Для биллинга и финансов, где нужна точность, он не подходит.
Связанные темы
- EXPLAIN и план запроса для DE
- Vector databases для DS
- Cumulative DISTINCT для DE
- Транзакции и MVCC для DE
- Подготовка к собесу Data Engineer
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+ вопросами для собесов.