You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

查询2198条数据耗时近6分钟,如何优化Django API查询速度?

优化Django Product表查询速度的方案

首先明确问题核心:当前代码触发了N+1查询——主查询拉取所有Product后,序列化时每个Product都要单独查询一次Brand表,直接导致2000+次SQL请求,这是耗时的根本原因。以下是具体优化方案:

1. 预取关联外键数据(解决N+1查询)

用select_related一次性连表查询Product和关联的Brand数据,把原本2000+次SQL请求合并为1次:

@api_view(['GET'])
def autofill_api(request):
    # 用select_related预取brand关联数据
    items = Product.objects.all().select_related('brand')
    serializer = AutoFillSerializer(items, many=True)
    return Response(serializer.data)

注意:select_related适用于ForeignKey/OneToOneField这类多对一/一对一关联;如果涉及ManyToManyField关联,需改用prefetch_related。

2. 避免序列化所有字段

当前fields = __all__会返回Product表的所有字段,若存在大量前端不需要的字段(如创建时间、内部状态字段),会增加数据传输和序列化耗时。明确指定需要的字段:

class AutoFillSerializer(serializers.ModelSerializer):
    brand_name = serializers.CharField(source='brand.brand')

    class Meta:
        model = Product
        # 只列出前端需要的字段,示例:
        fields = ['id', 'product_name', 'price', 'brand_name']

3. 分页返回数据

如果Product表数据量较大(2000条左右),一次性返回所有数据会导致响应包过大、前端加载慢。用Django REST Framework的分页器拆分数据:

from rest_framework.pagination import PageNumberPagination

class ProductPagination(PageNumberPagination):
    page_size = 100  # 每页返回100条数据
    page_size_query_param = 'page_size'
    max_page_size = 500

@api_view(['GET'])
def autofill_api(request):
    items = Product.objects.all().select_related('brand')
    # 应用分页
    paginator = ProductPagination()
    paginated_items = paginator.paginate_queryset(items, request)
    serializer = AutoFillSerializer(paginated_items, many=True)
    return paginator.get_paginated_response(serializer.data)

前端可通过?page=1、?page=2分页获取数据,大幅降低单次请求的耗时。

4. 直接查询所需字段(跳过模型实例序列化)

如果不需要完整的Product模型实例,用values直接查询结构化数据,减少模型实例创建和序列化的开销:

from django.db.models import F

@api_view(['GET'])
def autofill_api(request):
    # 直接查询需要的字段,包括关联的brand名称
    items = Product.objects.all().select_related('brand').values(
        'id', 'product_name', 'price', brand_name=F('brand__brand')
    )
    return Response(list(items))

这种方式无需Serializer,响应速度更快,适合只需要基础数据的场景。

5. 数据库层面优化

  • 确保外键字段brand_id有索引:Django默认会给ForeignKey字段创建索引,若之前手动删除过,需重新添加;
  • 若数据量达十万级以上,给常用查询字段(如product_name、brand_id)添加联合索引,进一步提升查询效率。

6. 缓存策略优化(兼顾实时性)

若使用cache_page,可通过以下方式平衡缓存命中率和实时性:

  • 设置较短的缓存过期时间(如5分钟);
  • 用Django信号监听Product或Brand的更新/删除事件,自动清除对应缓存,确保用户能及时看到最新数据:
from django.core.cache import cache
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver

@receiver(post_save, sender=Product)
@receiver(post_delete, sender=Product)
@receiver(post_save, sender=Brand)
@receiver(post_delete, sender=Brand)
def clear_autofill_cache(sender, **kwargs):
    # 删除autofill_api的缓存
    cache.delete_pattern('views.decorators.cache.cache_page.*autofill_api*')

内容的提问来源于stack exchange,提问作者Hector Devough

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:43:09