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

2014-09-05 17:19:09 +08:00
 no13bus
mysqldb 竟然达到了 24 个连接,数据处理到了 4w 行的时候 内存快达到了 94%,直接被 killed 掉了。这个怎么解决?
5730 次点击
所在节点    Python
21 条回复
wenbinwu
2014-09-05 17:36:43 +08:00
你代码怎么写的啊?
yueyoum
2014-09-05 17:40:45 +08:00
不是 mysqldb 的问题, 你代码写错了

上代码
magine
2014-09-05 18:02:28 +08:00
围观代码QAQ
no13bus
2014-09-05 18:18:48 +08:00
no13bus
2014-09-05 18:30:42 +08:00
@magine 来吧。
magine
2014-09-05 18:44:16 +08:00
@no13bus
其实我只是特别关注了 yueyoum 尾随着学django的小白……
adieu
2014-09-05 19:01:48 +08:00
@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
2014-09-05 20:37:22 +08:00
遇到过这种问题,最后用程序分段处理解决的。
no13bus
2014-09-05 20:57:49 +08:00
@adieu 你的方法非常有效。1 2已经解决了。内存占用一直稳定,没有再往上升。是不是说.iterator()在内存不够用的时候 可以采用,如果内存够用的话 就让query result开着,利于数据库查询?
@hustlzp .iterator()这个东西比较给力。
wenbinwu
2014-09-05 21:02:05 +08:00
像ls说的,可以一次取几千个,处理完了再取。
另外,那个re_minitor_info是什么?会不会造成另一个查询?
wenbinwu
2014-09-05 21:03:00 +08:00
突然想起来,如果是django命令内存过高的话是正常的
no13bus
2014-09-05 21:10:51 +08:00
@wenbinwu 恩。这个就是做成的django的命令。写在了management里面了。为什么命令导致内存高是正常的?
no13bus
2014-09-05 21:11:24 +08:00
@wenbinwu 是的,他也是models里面的一个表。
bcxx
2014-09-05 21:38:15 +08:00
@no13bus iterator 那个是 lazy 的 内存不够的时候就用这种接口吧(pyton 里面很多类似的)
no13bus
2014-09-05 21:48:57 +08:00
@bcxx 对。
est
2014-09-05 22:18:46 +08:00
硬tab,for里面嵌套3层if。。。。
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
2014-09-06 01:27:45 +08:00
@adieu nice
no13bus
2014-09-06 09:03:45 +08:00
@est 软tab是空格?
eriale
2014-09-06 09:50:56 +08:00
@adieu 学习了。给你点赞

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/131956

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX