Расскажи про опыт работы с PostgreSQL
PostgreSQL — это мощная реляционная СУБД с расширенными возможностями, которую я активно использовал в Node.js-проектах. В работе я применял как нативный драйвер pg, так и ORM (Sequelize, TypeORM) в зависимости от задачи. Ключевые аспекты: эффективное управление подключениями через пул, использование транзакций для целостности данных, работа с JSONB для гибкого хранения и подготовленные выражения для безопасности.
Как это работает
В Node.js основным способом взаимодействия с PostgreSQL является драйвер pg. Он предоставляет два основных API: Client для одиночных подключений и Pool для управления пулом соединений. Пул особенно важен в веб-приложениях, так как создание нового подключения — дорогая операция. Пример настройки пула:
const { Pool } = require('pg');
const pool = new Pool({
user: 'dbuser',
host: 'localhost',
database: 'mydb',
password: 'secret',
port: 5432,
max: 10, // максимальное число соединений в пуле
idleTimeoutMillis: 30000,
});
async function getUsers() {
const res = await pool.query('SELECT * FROM users WHERE active = $1', [true]);
return res.rows;
}
Здесь `$1` — это параметризованный запрос, который защищает от SQL-инъекций. Драйвер автоматически использует prepared statements для повторяющихся запросов, что повышает производительность.
## Транзакции и продвинутые возможности
Транзакции обеспечивают атомарность операций. В `pg` их можно реализовать через `BEGIN`/`COMMIT`/`ROLLBACK`, но удобнее использовать клиент из пула:
```javascript
const client = await pool.connect();
try {
await client.query('BEGIN');
await client.query('UPDATE accounts SET balance = balance - 100 WHERE id = $1', [1]);
await client.query('UPDATE accounts SET balance = balance + 100 WHERE id = $1', [2]);
await client.query('COMMIT');
} catch (err) {
await client.query('ROLLBACK');
throw err;
} finally {
client.release();
}PostgreSQL также поддерживает тип JSONB, который позволяет хранить документы и эффективно индексировать их содержимое. Это удобно для гибких схем данных. Для сложных выборок я использовал CTE (WITH-запросы) и оконные функции (ROW_NUMBER(), SUM() OVER), что упрощает аналитические запросы.
Подводные камни
- Утечка соединений: если не вызывать
client.release()или не закрыватьPool, соединения исчерпаются. Всегда используйтеtry/finallyилиasync-менеджеры. - N+1 запросов: при использовании ORM легко попасть в ловушку множественных запросов. Решается через
JOINилиeager loading. - Миграции: без системы миграций (например,
node-pg-migrate) сложно поддерживать схему БД в команде. - Производительность: для массовых операций лучше использовать
COPYили батч-вставки, а не циклы с отдельнымиINSERT.
Когда использовать
PostgreSQL — отличный выбор для проектов, требующих надёжности, сложных запросов и гибкости данных. В Node.js он хорошо сочетается с Express/NestJS. ORM (Sequelize, TypeORM) ускоряет разработку, но для высоконагруженных систем лучше использовать нативный pg с ручной оптимизацией запросов.
Коротко
- Основной драйвер —
pg, используйтеPoolдля управления соединениями. - Всегда применяйте параметризованные запросы для защиты от SQL-инъекций.
- Транзакции обязательны для операций, изменяющих несколько таблиц.
- Используйте
JSONB, CTE и оконные функции для сложных сценариев. - Следите за утечками соединений и избегайте N+1 запросов в ORM.
