Update nexus wiki content
This commit is contained in:
62
wiki/concepts/N1QueryPrevention.md
Normal file
62
wiki/concepts/N1QueryPrevention.md
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
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 是生产环境性能问题的常见根源
|
||||
Reference in New Issue
Block a user