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

DRF大型GET请求触发504网关超时,如何无分页获取百万级数据?

解决300万条记录无分页加载的方案

针对你遇到的大数量级数据加载导致服务器崩溃、超时问题,从数据库查询、后端接口、前端加载三个维度给出优化方案,全程无需分页或过滤:

1. 数据库查询层面砍数据量

  • 只拉取必要字段:别用Model.objects.all()加载完整模型实例,改用values()或only()仅获取前端需要的字段,能大幅减少传输的数据体积。比如:
    # 只取id、name、data三个字段
    YourModel.objects.values('id', 'name', 'data')
    
  • 用原生查询替代ORM:Django ORM虽然方便,但处理超大量数据时会有额外开销。直接用原生SQL查询,通过游标逐行读取:
    from django.db import connection
    
    def get_raw_records():
        with connection.cursor() as cursor:
            cursor.execute("SELECT id, name, data FROM your_table_name")
            columns = [col[0] for col in cursor.description]
            # 逐行生成字典,避免一次性加载全部数据
            for row in cursor:
                yield dict(zip(columns, row))
    
  • 关闭不必要的关联与信号:如果模型有外键且前端不需要关联数据,别用select_related/prefetch_related;临时关闭模型的post_save等信号,减少额外的处理逻辑消耗资源。

2. 后端接口优化,避免超时

  • 弃用DRF,用轻量级响应:DRF的序列化器、权限校验等中间件会增加响应时间,直接用Django原生的StreamingHttpResponse返回流式JSON,跳过不必要的开销:
    import json
    from django.http import StreamingHttpResponse
    from .models import YourModel
    
    def stream_all_records(request):
        def generate_stream():
            yield '['
            first_item = True
            # 用iterator()逐行从数据库取数据,不占内存
            for item in YourModel.objects.values('id', 'name', 'data').iterator():
                if not first_item:
                    yield ','
                yield json.dumps(item)
                first_item = False
            yield ']'
        return StreamingHttpResponse(generate_stream(), content_type='application/json')
    
  • 调整服务器超时配置:Apache默认超时时间较短,修改httpd.conf里的Timeout参数(比如设为300秒),同时调整WSGI模块的process-timeout参数,给足够时间完成数据传输;条件允许的话换成uWSGI+Nginx的组合,处理大请求的性能比Apache好很多。
  • 关闭Django调试模式:生产环境务必把DEBUG设为False,调试模式下的额外检查会大幅增加资源消耗。

3. 前端流式接收,避免内存溢出

前端直接接收全量JSON容易导致内存崩溃,用Fetch API的流式处理逐步接收并解析数据:

fetch('/api/stream-all-records/')
  .then(res => {
    const reader = res.body.getReader();
    const decoder = new TextDecoder();
    let partialData = '';
    
    function processChunk({ done, value }) {
      if (done) {
        // 最后一块数据处理完,解析完整JSON
        const fullData = JSON.parse(partialData);
        // 在这里渲染全部数据
        return;
      }
      // 解码当前块并拼接
      partialData += decoder.decode(value, { stream: true });
      // 可选:这里可以先渲染已接收的部分数据
      return reader.read().then(processChunk);
    }
    
    return reader.read().then(processChunk);
  });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:42:40