V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
dapengzhao
V2EX  ›  问与答

django 查询得到很大的 queryset,该如何快速遍历,有了解的大佬解答一下?

  •  
  •   dapengzhao · 2019-08-05 14:30:05 +08:00 · 2641 次点击
    这是一个创建于 1936 天前的主题,其中的信息可能已经有所发展或是发生改变。

    diango orm 查询 postgres 数据库一张表,从 1 亿数据中查询,有个条件会查到 600 多万条数据,我要对查到的数据集做遍历生成需要的格式。这个过程大概需要 70 到 80 秒。由于查到的数据要图像化到前端,这个等待过程有点太长。

    for al in res:
        bytes_list.append(al['in_bytes'] + al['out_bytes'])
        packets_list.append(al['in_pkts'] + al['out_pkts'])
        time_list.append(al['start_time']).strftime("%Y-%m-%d %H:%M:%S"))
    

    res 就是得到的 queryset,下面*__list 是三个空列表

    14 条回复    2019-08-06 07:47:32 +08:00
    leishi1313
        1
    leishi1313  
       2019-08-05 14:43:58 +08:00 via Android
    你这条 for 可以用 sql 直接得到结果。然后查询这么慢的话可以放缓存。
    009694
        2
    009694  
       2019-08-05 15:12:06 +08:00
    bytes_list = [al['in_bytes'] + al['out_bytes'] for al in res]
    packets_list = [al['in_pkts'] + al['out_pkts'] for al in res]
    time_list = [al['start_time'].strftime("%Y-%m-%d %H:%M:%S") for al in res]
    ankazen
        3
    ankazen  
       2019-08-05 15:12:12 +08:00
    为什么一次性需要这么多数据呢?是不是需要设计中间层去存储查新结果?
    dapengzhao
        4
    dapengzhao  
    OP
       2019-08-05 15:17:22 +08:00
    @009694 这样写用时 75 秒,跟之前的 for 循环差不多
    dapengzhao
        5
    dapengzhao  
    OP
       2019-08-05 15:19:28 +08:00
    @leishi1313 有点没看懂你的意思是说可以在 sql 里面就得到想要的结果?然后说先将结果放缓存我理解成 res = [r for r in res]这样先存起来再查?这样的话分别用时 33 秒,45 秒和直接 for 循环也差不多
    dapengzhao
        6
    dapengzhao  
    OP
       2019-08-05 15:20:36 +08:00
    @ankazen 因为查询条件是用户选择的,选的查询条件越少查出来的数据就越多
    misaka19000
        7
    misaka19000  
       2019-08-05 15:25:04 +08:00
    一次查询 600 万条数据?你这个简单,改需求
    dapengzhao
        8
    dapengzhao  
    OP
       2019-08-05 15:29:22 +08:00
    @misaka19000 好嘞哥
    pkuphy
        9
    pkuphy  
       2019-08-05 15:29:39 +08:00
    list(res
    .annotate(
    bytes=F('in_bytes')+F('out_bytes'),
    packets=F('in_pkts')+F('out_pkts')
    ).values(
    'bytes', 'packets', 'start_time'
    )
    )
    leishi1313
        10
    leishi1313  
       2019-08-05 15:48:21 +08:00 via Android
    @dapengzhao sql 里也可以计算吧,select val1+val2,psql 也能直接对 datetime 进行格式化操作,照着#9 的做就好,你这一整个 for 是完全可以放在数据库做的。再说了拿 python 的 list append 600 多万条数据也太难为人了,后面这些数据要聚合的话试试 generator 吧。还有你前端不要分页的吗一次拿那么多数据
    dapengzhao
        11
    dapengzhao  
    OP
       2019-08-05 15:54:30 +08:00
    @leishi1313 我也在想要把这个过程写成存储过程,前端只要 list 就行,画两个散点图
    wzwwzw
        12
    wzwwzw  
       2019-08-05 22:38:54 +08:00
    曲线救国,把计算好的数据放到缓存,开个线程在后台几分钟计算一下。
    leishi1313
        13
    leishi1313  
       2019-08-06 01:40:05 +08:00
    @dapengzhao 我不是建议存储过程啊,我意思跟#9 差不多,你这可以用一条 query 直接在数据库查询出来的,用 Django 可以看看 annotate 和 extra 这两个就可以达到你的效果了
    wd
        14
    wd  
       2019-08-06 07:47:32 +08:00 via iPhone
    提前把所有可能算出来存好
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2801 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 13:13 · PVG 21:13 · LAX 05:13 · JFK 08:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.