> Расскажите про опыт работы с PostgreSQL (JavaScript)
Уровень: senior · Роль: backend · Язык: JavaScript · Категория: Технические вопросы
Компании: ЭНИРАН
Стек: Node.js, JavaScript, PostgreSQL
> Пример ответа
Короткий ответ
PostgreSQL - моя основная реляционная БД в production. Работаю с ней более 5 лет: проектирование схем, оптимизация запросов, миграции, настройка индексов, работа с JSONB, full-text search, оконные функции. В связке с Node.js использую pg (node-postgres) с пулом соединений, транзакциями и prepared statements. Сталкивался с replication, partitioning, vacuum tuning и мониторингом через pg_stat_statements.
Подробное объяснение
PostgreSQL - это объектно-реляционная СУБД с ACID compliance, MVCC, расширяемой системой типов и мощным планировщиком запросов. В production-проектах на Node.js я использую её для:
- Схемы и миграции: проектирую нормализованные схемы с foreign keys, unique constraints, check constraints. Миграции через sqitch или flyway.
- Индексы: B-tree, GIN для JSONB/массивов, GiST для full-text search, partial и covering indexes.
- JSONB: хранение гибких структур с индексацией, обновление через
jsonb_set, агрегация черезjsonb_agg. - Full-text search: tsvector/tsquery с конфигурациями русского и английского языка, weighted search.
- Оконные функции:
ROW_NUMBER(),LAG(),SUM() OVERдля пагинации, аналитики, дедупликации. - Транзакции: управление через
BEGIN/COMMIT/ROLLBACK, savepoints, изоляция READ COMMITTED (по умолчанию) и SERIALIZABLE для конкурентных обновлений. - Connection pooling: pg-pool с настройкой max/min, idle timeout, statement timeout.
- Мониторинг: pg_stat_statements для поиска медленных запросов, auto_explain для логирования планов.
На практике
В типичном Node.js-приложении:
- pg как драйвер, knex или slonik для построения запросов (raw SQL для сложных случаев).
- Пул соединений:
new Pool({ max: 20, idleTimeoutMillis: 30000 })- один пул на процесс, переиспользуется между запросами. - Миграции: каждая миграция - отдельный SQL-файл, запускается при старте приложения или через CLI.
- Оптимизация: EXPLAIN ANALYZE для проблемных запросов, добавление индексов по фильтрам WHERE и JOIN, избегание N+1 через batch loading (DataLoader).
- Обработка ошибок: retry logic для serialization failures, graceful shutdown с закрытием пула.
Пример кода
JAVASCRIPTconst { Pool } = require('pg');const pool = new Pool({host: process.env.DB_HOST,database: 'mydb',max: 20,idleTimeoutMillis: 30000,statement_timeout: 5000,});// Транзакция с savepointasync function updateUserAndLog(userId, newEmail) {const client = await pool.connect();try {await client.query('BEGIN');await client.query('SAVEPOINT before_email_update');const result = await client.query('UPDATE users SET email = $1 WHERE id = $2 RETURNING *',[newEmail, userId]);if (result.rows.length === 0) {await client.query('ROLLBACK TO SAVEPOINT before_email_update');throw new Error('User not found');}await client.query('INSERT INTO audit_log (user_id, action) VALUES ($1, $2)',[userId, 'email_updated']);await client.query('COMMIT');return result.rows[0];} catch (err) {await client.query('ROLLBACK');throw err;} finally {client.release();}}// Полнотекстовый поиск с ранжированиемasync function searchPosts(query) {const result = await pool.query(`SELECTtitle,ts_rank(search_vector, query) AS rankFROM posts, plainto_tsquery('russian', $1) AS queryWHERE search_vector @@ queryORDER BY rank DESCLIMIT 20`, [query]);return result.rows;}
Как отвечать на собеседовании
Начни с конкретных проектов: "В проекте X использовал PostgreSQL для хранения заказов с JSONB-полями, оптимизировал запросы через GIN-индексы". Покажи понимание trade-off: нормализация vs JSONB, B-tree vs GIN, READ COMMITTED vs SERIALIZABLE. Упомяни инструменты: pg_stat_statements, EXPLAIN ANALYZE, pgBadger. Если спросят про проблемы - расскажи про bloat, autovacuum tuning, lock contention.
Что проверяет интервьюер
- Глубину практического опыта (не просто "знаю SQL", а конкретные кейсы).
- Понимание внутренностей PostgreSQL: MVCC, vacuum, lock levels, планировщик.
- Умение проектировать схемы и выбирать индексы под нагрузку.
- Навыки работы с Node.js: пул соединений, транзакции, обработка ошибок.
- Знание продвинутых фич: оконные функции, full-text search, JSONB.
Типичные ошибки
- Использование
SELECT *в production - лишние данные, нагрузка на I/O. - Отсутствие индексов на внешние ключи - блокировки при DELETE/UPDATE.
- Игнорирование statement timeout - зависшие запросы блокируют пул.
- Неправильная настройка пула: слишком много соединений (каждый процесс Node.js свой пул) или слишком мало (очереди).
- Забывают про
client.release()в catch/finally - утечка соединений. - Использование ORM без понимания генерируемого SQL - N+1, неэффективные запросы.
> Похожие задачи по JavaScript
Что такое Redis Cluster
Как работать со сложными запросами в PostgreSQL
Что такое GridFS в MongoDB
Как решать проблему нагрузки на CPU в сервисе
> Похожие задачи по backend
Что такое Redis Cluster
Как работать со сложными запросами в PostgreSQL
Что такое GridFS в MongoDB
Как решать проблему нагрузки на CPU в сервисе
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью