Files
djangoadmin-wiki/DjangoAdmin_Django_AntdVue/zh/volume6/performance.md
T
2026-09-12 23:12:15 +08:00

201 lines
5.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.
# 性能调优
## 概述
Django 应用的性能调优涉及 Gunicorn Worker 配置、数据库连接池、Redis 缓存策略、慢查询优化等多个层面。合理的调优能显著提升并发处理能力和响应速度。
:::tip 性能调优原则
1. 先测量,后优化:用数据说话,避免盲目调参
2. 瓶颈优先:找到最大瓶颈,集中优化
3. 渐进式:每次只调整一个参数,观察效果
:::
## Gunicorn Worker 配置
### Worker 数量
```bash
# 单 Worker(开发环境)
python manage.py runserver
# 多 Worker(生产环境)
gunicorn application.wsgi:application --bind 0.0.0.0:8000 --workers 4
```
:::tip Worker 数量公式
推荐 Worker 数量 = `CPU 核心数 * 2 + 1`
例如 4 核 CPU:`workers = 4 * 2 + 1 = 9`
查看 CPU 核心数:
```bash
# Linux
nproc
# Python
import multiprocessing; print(multiprocessing.cpu_count())
```
:::
### 启动方式选择
| 方式 | 适用场景 | 特点 |
|------|---------|------|
| `python manage.py runserver` | 开发调试 | 单进程,自动重载 |
| `gunicorn` | 生产部署 | 多进程,成熟的进程管理 |
### Gunicorn 配置示例
```bash
pip install gunicorn
gunicorn application.wsgi:application \
--bind 0.0.0.0:8000 \
--workers 4 \
--timeout 120 \
--keep-alive 5 \
--max-requests 1000 \
--max-requests-jitter 50
```
:::tip max-requests 作用
`--max-requests 1000` 表示每个 Worker 处理 1000 个请求后自动重启,防止内存泄漏累积。`--max-requests-jitter 50` 添加随机抖动,避免所有 Worker 同时重启。
:::
## 数据库连接池
Django 使用 `django.db.backends` 内置连接池,可通过 `DATABASES` 配置中的 `CONN_MAX_AGE` 控制连接复用:
```python
# application/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'djangoadmin_prod',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'djangoadmin',
'PASSWORD': '<强密码>',
'CONN_MAX_AGE': 600, # 连接存活时间(秒),0 表示每次请求新建连接
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
},
}
}
```
| 参数 | 说明 | 推荐值 |
|:----|:----|:----|
| `CONN_MAX_AGE` | 连接存活时间(秒) | `600`(10分钟) |
:::warning 连接池大小
Django 默认每个请求使用独立连接。高并发场景可考虑使用 `django-db-connection-pool` 等第三方包管理连接池。
:::
## Redis 缓存优化
### 缓存策略
| 策略 | 适用场景 | 实现方式 |
|------|---------|---------|
| 读缓存 | 字典、配置等读多写少 | 查询时先读 Redis,未命中再查 DB |
| 写失效 | 数据更新时 | 更新 DB 后删除 Redis 缓存 |
| 预热 | 服务启动时 | 启动后主动加载热点数据到 Redis |
### TTL 设置建议
```python
# 字典数据:较长 TTL(变更频率低)
DICT_CACHE_TTL = 3600 # 1 小时
# 用户权限:中等 TTL(登录时刷新)
PERM_CACHE_TTL = 1800 # 30 分钟
# 验证码:短 TTL(一次性使用)
CAPTCHA_CACHE_TTL = 300 # 5 分钟
```
## 慢查询优化
### 开启慢查询日志
MySQL:
```sql
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
```
### 常见优化手段
| 问题 | 优化方案 |
|------|---------|
| 缺少索引 | 为 WHERE/ORDER BY 字段添加索引 |
| 全表扫描 | 使用 EXPLAIN 分析查询计划 |
| N+1 查询 | 使用 `select_related`/`prefetch_related` 预加载关联数据 |
| 大分页 | 使用游标分页或延迟关联 |
| SELECT * | 只查询需要的字段(`.values()` 或 `.only()`) |
### 索引优化示例
```python
# 模型定义中添加索引
class Article(BaseModel):
title = models.CharField(max_length=255, db_index=True) # 单列索引
status = models.IntegerField(db_index=True)
category_id = models.IntegerField(db_index=True)
class Meta:
db_table = get_table_name('article')
indexes = [
models.Index(fields=['status', 'category_id'], name='idx_status_category'), # 复合索引
]
```
### 分页查询优化
```python
# 避免大分页:使用游标分页
# 差:OFFSET 100000 LIMIT 10(扫描大量数据)
# 好:WHERE id > last_id LIMIT 10(利用主键索引)
def paginate_after_id(queryset, last_id, limit=10):
"""游标分页:基于上次最后一条记录的 ID"""
return queryset.filter(id__gt=last_id).order_by('id')[:limit]
```
## 查询优化
### select_related 和 prefetch_related
```python
# N+1 问题示例(差)
articles = Article.objects.filter(status=1)
for article in articles:
print(article.category.name) # 每次循环都查询一次数据库
# 优化:使用 select_related(外键关联)
articles = Article.objects.filter(status=1).select_related('category')
for article in articles:
print(article.category.name) # 已预加载,不再查询
# 优化:使用 prefetch_related(多对多关联)
users = User.objects.prefetch_related('roles')
for user in users:
print(user.roles.all()) # 已预加载
```
### values() 和 only()
```python
# 只查询需要的字段
users = User.objects.filter(status=1).values('id', 'username', 'email')
# 或使用 only()
users = User.objects.filter(status=1).only('id', 'username', 'email')
```
## 总结
性能调优的核心路径:Gunicorn 多 Worker 利用多核 CPU、数据库连接池匹配并发需求、Redis 缓存减少 DB 压力、索引和查询优化降低慢查询。建议先用监控数据定位瓶颈,再针对性调优,每次只调整一个参数并观察效果。