Django性能优化 - 提升应用响应速度与并发能力

📂 所属阶段:第三部分 — 高级主题 | 🎯 难度等级:高级 | ⏰ 预计学习时间:6-8小时
🎒 前置知识:缓存策略, 数据库查询优化


性能优化概述

性能优化直接影响用户留存和系统扩容成本,必须遵循「先测量、后优化」的原则

核心优化方向

根据80/20法则,我们优先关注以下3个90%瓶颈贡献项:

  1. 数据库查询(N+1、无索引、重复查询)
  2. 缓存策略(命中率、失效逻辑)
  3. 资源加载(静态文件、API依赖)

数据库查询优化

数据库是Django应用最大的性能黑洞,这里提供最实用的ORM优化方案。

解决N+1查询

# ❌ 错误做法:遍历每篇文章时,单独查询作者、标签、评论
# posts = Post.objects.all()
# for post in posts:
#     print(post.author.username, [t.name for t in post.tags.all()])

# ✅ 正确做法:外键一对一用select_related,一对多多对多用prefetch_related
from django.db.models import Prefetch
from django.contrib.auth.models import User

class Tag(models.Model): name = models.CharField(max_length=50)
class Comment(models.Model): post = models.ForeignKey('Post', on_delete=models.CASCADE)
class Post(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    tags = models.ManyToManyField(Tag)
    comments = models.ManyToManyField(Comment)

posts = Post.objects.select_related('author')\
    .prefetch_related(
        'tags',
        Prefetch('comments', queryset=Comment.objects.select_related('user').order_by('-created_at')[:5])
    ).filter(status='published')

加载字段优化

# 只加载必要的字段,避免大内容/无用字段拖累
from django.contrib.auth.models import User

# ✅ 只查username、email
light_users = User.objects.only('username', 'email')

# ✅ 排除大字段content
articles = Article.objects.defer('content')

批量操作与聚合

# 批量更新比循环save快数十倍
Post.objects.filter(status='draft').update(status='archived')

# 分组聚合在数据库完成,不要在Python循环处理
from django.db.models import Count
categories = Category.objects.annotate(post_count=Count('posts'))

性能分析工具

基础SQL分析

from django.db import connection

# 打印当前请求的所有SQL(调试用)
print(connection.queries)

生产级工具

推荐安装 django-debug-toolbar(开发)和 django-silk(生产轻量)。


缓存策略优化

合理的缓存可以将响应时间从秒级降到毫秒级,缓存失效是最大的难点。

常用缓存方式

from django.core.cache import cache
from django.views.decorators.cache import cache_page

# 1️⃣ 视图缓存(整个页面)
@cache_page(60 * 15)  # 缓存15分钟
def hot_products(request):
    products = Product.objects.filter(views__gt=1000)
    return render(request, 'hot_products.html', {'products': products})

# 2️⃣ 片段缓存(模板部分)
"""
{% load cache %}
{% cache 600 hot_product_sidebar request.user.id %}
    <!-- 这里的内容每10分钟更新一次,且按用户ID区分 -->
{% endcache %}
"""

# 3️⃣ 函数/方法缓存
def get_user_profile(user_id):
    key = f'profile:{user_id}'
    profile = cache.get(key)
    if not profile:
        profile = UserProfile.objects.get(user_id=user_id)
        cache.set(key, profile, 60 * 5)  # 缓存5分钟
    return profile

避免缓存雪崩与穿透

# 解决缓存穿透:空值缓存
def get_product(id):
    key = f'product:{id}'
    product = cache.get(key)
    if product is None:
        try:
            product = Product.objects.get(id=id)
            cache.set(key, product, 60 * 5)
        except Product.DoesNotExist:
            cache.set(key, 'empty', 60)  # 空值缓存60秒
    if product == 'empty':
        return None
    return product

# 解决缓存雪崩:随机过期时间
import random
cache.set(key, value, 60 * 5 + random.randint(0, 60))  # 加0-60秒随机偏移

异步处理优化

对于I/O密集型任务(发送邮件、调用外部API、处理图片),异步可以释放主线程,提升并发能力。

Celery异步任务

# 安装依赖
# pip install celery redis

# celery.py
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
app = Celery('myproject')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()

# settings.py
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/1'
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/2'

# tasks.py
from celery import shared_task

@shared_task
def send_welcome_email(email):
    # 模拟耗时的邮件发送
    import time
    time.sleep(3)
    print(f'Welcome email sent to {email}')

# views.py 中调用
def register(request):
    # ... 注册逻辑
    send_welcome_email.delay(user.email)  # 异步调用,不阻塞
    return redirect('home')

静态文件优化

静态文件加载时间影响页面首屏渲染,优先处理。

基础配置

# settings.py
from django.contrib.staticfiles.storage import ManifestStaticFilesStorage

STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_STORAGE = ManifestStaticFilesStorage  # 自动添加哈希后缀,避免缓存失效

CDN加速

生产环境将静态文件上传到CDN,修改STATIC_URL即可:

# settings.py 生产配置
STATIC_URL = 'https://cdn.yourdomain.com/static/'

部署优化

生产环境部署配置对性能影响同样巨大,推荐使用 Gunicorn + Nginx + Redis + PostgreSQL 架构。

Gunicorn配置

# gunicorn.conf.py
bind = "127.0.0.1:8000"
workers = 2 * os.cpu_count() + 1  # CPU核心数的2倍加1
worker_class = "sync"  # I/O密集用gevent,计算密集用sync
timeout = 30
max_requests = 1000  # 重启worker,避免内存泄漏

本章小结

  1. 数据库优化是核心:解决N+1、索引优化、批量操作
  2. 缓存是加速器:合理使用缓存、避免雪崩穿透
  3. 异步释放压力:I/O密集任务用Celery
  4. 监控持续优化:使用django-debug-toolbar、django-silk

🔗 相关教程

🏷️ 标签云: Django性能优化 数据库优化 缓存策略 异步处理 Celery