Files
nexus/wiki/concepts/N1QueryPrevention.md
2026-05-03 05:42:12 +08:00

63 lines
1.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "N+1 Query Prevention"
type: concept
tags: [database, performance, n+1, postgresql, query-optimization]
last_updated: 2026-05-01
---
# N+1 Query Prevention
## Definition
N+1 查询问题是指应用程序在获取一组主对象后,对每个对象分别发起一次额外查询来获取关联数据的反模式。假设获取 N 个用户,每个用户查一次帖子,总共产生 1 + N 次数据库往返。
## The Problem
```typescript
// ❌ Bad: N+1 pattern
const users = await db.query("SELECT * FROM users LIMIT 10");
for (const user of users) {
user.posts = await db.query(
"SELECT * FROM posts WHERE user_id = $1",
[user.id]
);
}
// 1 + 10 = 11 queries
```
## The Solution
```typescript
// ✅ Good: Single query with aggregation
const usersWithPosts = await db.query(`
SELECT
u.id, u.email, u.name,
COALESCE(
json_agg(
json_build_object('id', p.id, 'title', p.title)
) FILTER (WHERE p.id IS NOT NULL),
'[]'
) as posts
FROM users u
LEFT JOIN posts p ON p.user_id = u.id
GROUP BY u.id
LIMIT 10
`);
// 1 query
```
## Key Techniques
- **JOIN + json_agg**PostgreSQL 下用 `json_agg` 聚合嵌套关联数据
- **批量查询Batch Loading**:拆分为 2-3 次查询IN 子句分批)
- **预加载Eager Loading**ORM 的 `include` / `preload` 机制
- **物化视图**:对稳定结构做预计算
## Source
- [[engineering-database-optimizer]]
## Connections
- [[QueryPlanAnalysis]] — 通过 EXPLAIN ANALYZE 识别 N+1
- [[engineering-backend-architect]] — 架构设计时需避免 N+1
- [[engineering-sre]] — N+1 是生产环境性能问题的常见根源