проектdocs/Agents/rules/performance-database-queries.md
performance-database-queries.md
Обновлён 1 апр. 2026 г., 12:41 · 0 комментариев
title: Database Query Optimization impact: HIGH impactDescription: Prevents N+1 queries and ensures fast page loads tags: performance, database, prisma, postgresql, indexing
Паспорт документа
- Статус документа: living standard
- Актуально на: 28 марта 2026 года
- Владелец: backend/platform-команда
- Пересмотр: при изменении инженерной практики, CI/CD, архитектурных правил или локального workflow
- Область применения: внутренние rule/reference-card документы для инженерной команды
- Связанные документы:
Database Query Optimization
Impact: HIGH
Avoid N+1 Queries
// Bad: N+1 — one query per item for seller data
const items = await this.prisma.item.findMany({ where: { status: 'PUBLISHED' } });
for (const item of items) {
item.seller = await this.prisma.seller.findUnique({ where: { id: item.sellerId } });
}
// Good: single query with select
const items = await this.prisma.$replica().item.findMany({
where: { status: 'PUBLISHED' },
select: {
id: true,
title: true,
seller: {
select: { id: true, name: true, logoUrl: true }
}
}
});
Always Paginate
// Bad: load entire table
const items = await this.prisma.item.findMany();
// Good: paginated with cursor or offset
const items = await this.prisma.$replica().item.findMany({
where: { status: 'PUBLISHED' },
select: { id: true, title: true, price: true },
skip: (page - 1) * limit,
take: limit,
orderBy: { createdAt: 'desc' },
});
Indexing Strategy
Add indexes for:
- Columns used in
WHEREclauses (status,sellerId,subjectId) - Columns used in
ORDER BY(createdAt,price,rating) - Unique constraints (
slug,email,phoneNumber) - Foreign keys (Prisma adds these automatically)
- Composite indexes for common filter combinations
model Item {
id String @id @default(uuid())
slug String @unique
status ItemStatus
sellerId String
subjectId String
createdAt DateTime @default(now())
@@index([status, createdAt])
@@index([sellerId, status])
@@index([subjectId, status])
}
Rules
- Never fetch all rows — always paginate
- Never filter in JavaScript what can be filtered in SQL
- Always use
selectto fetch only needed fields - Add indexes for frequently filtered/sorted columns
- Use
count()separately for pagination metadata