V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
no13bus
V2EX  ›  Python

django 的 orm 操作数据库的时候,遍历数据库里面一个 value 字段不为空的数据行,进行数据处理。结果 mysqldb 使得内存快达到了 94%,直接被 killed 掉了。这个怎么解决?

  •  
  •   no13bus ·
    no13bus · 2014-09-05 17:19:09 +08:00 · 5791 次点击
    这是一个创建于 3714 天前的主题,其中的信息可能已经有所发展或是发生改变。
    mysqldb 竟然达到了 24 个连接,数据处理到了 4w 行的时候 内存快达到了 94%,直接被 killed 掉了。这个怎么解决?
    21 条回复    2014-11-25 17:40:28 +08:00
    wenbinwu
        1
    wenbinwu  
       2014-09-05 17:36:43 +08:00
    你代码怎么写的啊?
    yueyoum
        2
    yueyoum  
       2014-09-05 17:40:45 +08:00
    不是 mysqldb 的问题, 你代码写错了

    上代码
    magine
        3
    magine  
       2014-09-05 18:02:28 +08:00
    围观代码QAQ
    no13bus
        4
    no13bus  
    OP
       2014-09-05 18:18:48 +08:00
    no13bus
        5
    no13bus  
    OP
       2014-09-05 18:30:42 +08:00
    @magine 来吧。
    magine
        6
    magine  
       2014-09-05 18:44:16 +08:00
    @no13bus
    其实我只是特别关注了 yueyoum 尾随着学django的小白……
    adieu
        7
    adieu  
       2014-09-05 19:01:48 +08:00   ❤️ 1
    @no13bus 先试试两个最简单的优化:

    1. 在settings.py里面设DEBUG=False,当DEBUG=True时,默认是每个request过程中产生的sql查询都会被缓存下来,结束时flush。在Command里面的代码因为不在request里面,所以不会flush。那么会产生大量缓存的sql指令。
    2. result_list = results.objects.exclude(value='') 改为 result_list = results.objects.exclude(value='').iterator()。因为默认Django会缓存query result。

    如果这两个优化做了之后还会OOM,那就需要比较详细的调试了。用调试工具检测for循环没有被gc的变量有哪些。甚至放弃一次取回所有结果,用分段查询的办法。不过如果数据量不算太大的话,可能不会需要走那么远。
    hustlzp
        8
    hustlzp  
       2014-09-05 20:37:22 +08:00 via iPhone   ❤️ 1
    遇到过这种问题,最后用程序分段处理解决的。
    no13bus
        9
    no13bus  
    OP
       2014-09-05 20:57:49 +08:00
    @adieu 你的方法非常有效。1 2已经解决了。内存占用一直稳定,没有再往上升。是不是说.iterator()在内存不够用的时候 可以采用,如果内存够用的话 就让query result开着,利于数据库查询?
    @hustlzp .iterator()这个东西比较给力。
    wenbinwu
        10
    wenbinwu  
       2014-09-05 21:02:05 +08:00 via iPhone
    像ls说的,可以一次取几千个,处理完了再取。
    另外,那个re_minitor_info是什么?会不会造成另一个查询?
    wenbinwu
        11
    wenbinwu  
       2014-09-05 21:03:00 +08:00 via iPhone   ❤️ 1
    突然想起来,如果是django命令内存过高的话是正常的
    no13bus
        12
    no13bus  
    OP
       2014-09-05 21:10:51 +08:00
    @wenbinwu 恩。这个就是做成的django的命令。写在了management里面了。为什么命令导致内存高是正常的?
    no13bus
        13
    no13bus  
    OP
       2014-09-05 21:11:24 +08:00
    @wenbinwu 是的,他也是models里面的一个表。
    bcxx
        14
    bcxx  
       2014-09-05 21:38:15 +08:00
    @no13bus iterator 那个是 lazy 的 内存不够的时候就用这种接口吧(pyton 里面很多类似的)
    no13bus
        15
    no13bus  
    OP
       2014-09-05 21:48:57 +08:00
    @bcxx 对。
    est
        16
    est  
       2014-09-05 22:18:46 +08:00
    硬tab,for里面嵌套3层if。。。。
    adieu
        17
    adieu  
       2014-09-05 22:48:00 +08:00
    @no13bus 在考虑什么时候用.iterator()时需要考虑Django平常的使用场景。大部分的时候是在view里面把queryset传入到模板里面进行render。同一个queryset可能会多次遍历,如果每遍历一次就hit一次db,就一来浪费资源二来拖慢render时间。所以queryset本身是缓存的。

    不过有的时候在Command里面或者async task里面,需要对数据进行处理。那在明确知道这个queryset只会遍历一次的时候就可以用.iterator()取消掉cache。节约内存占用。

    平常如果数据量小,由于有gc,所以用起来区别不大。在数据量大的时候就是一个可以调优的点。
    no13bus
        18
    no13bus  
    OP
       2014-09-06 01:27:45 +08:00
    @adieu nice
    no13bus
        19
    no13bus  
    OP
       2014-09-06 09:03:45 +08:00
    @est 软tab是空格?
    eriale
        20
    eriale  
       2014-09-06 09:50:56 +08:00
    @adieu 学习了。给你点赞
    no13bus
        21
    no13bus  
    OP
       2014-11-25 17:40:28 +08:00
    @adieu 请问分段查询是什么意思?调试工具检测for循环没有被gc的变量有哪些。这个调试工具是什么?能举个例子吗?现在又遇到问题了,需要更新一个200w的数据。写成了django的命令格式。内存不够用了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3192 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 12:39 · PVG 20:39 · LAX 04:39 · JFK 07:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.