使用`delete()`时如何防止django在内存中加载对象?

git*_*rik 10 sql django django-models

我有内存问题,因为看起来Django在使用时将对象加载到内存中delete().有没有办法阻止Django这样做?

来自Django文档:

Django需要将对象提取到内存中以发送信号和处理级联.但是,如果没有级联和没有信号,那么Django可能会采用快速路径并删除对象而不会进入内存.对于大型删除,这可能会导致内存使用量大幅减少.执行查询的数量也可以减少.

https://docs.djangoproject.com/en/1.8/ref/models/querysets/#delete

我不使用信号.我在我试图删除的模型上有外键,但我不明白为什么Django需要将对象加载到内存中.它看起来确实如此,因为我的内存随着查询的运行而上升.

bax*_*ico 6

您可以使用这样的函数来迭代大量对象,而无需使用太多内存:

import gc

def queryset_iterator(qs, batchsize = 500, gc_collect = True):
    iterator = qs.values_list('pk', flat=True).order_by('pk').distinct().iterator()
    eof = False
    while not eof:
        primary_key_buffer = []
        try:
            while len(primary_key_buffer) < batchsize:
                primary_key_buffer.append(iterator.next())
        except StopIteration:
            eof = True
        for obj in qs.filter(pk__in=primary_key_buffer).order_by('pk').iterator():
            yield obj
        if gc_collect:
            gc.collect()
Run Code Online (Sandbox Code Playgroud)

然后您可以使用该函数迭代要删除的对象:

for obj in queryset_iterator(HugeQueryset.objects.all()):
    obj.delete()
Run Code Online (Sandbox Code Playgroud)

欲了解更多信息,您可以查看这篇博文


Sha*_*ang 2

可以导入django数据库连接,配合sql使用来删除。我遇到了和你完全相同的问题,这对我很有帮助。这是一些片段(顺便说一句,我正在使用 mysql,但你可以运行任何 sql 语句):

from django.db import connection
sql_query = "DELETE FROM usage WHERE date < '%s' ORDER BY date" % date
cursor = connection.cursor()
try:
    cursor.execute(sql_query)
finally:
    c.close()
Run Code Online (Sandbox Code Playgroud)

这应该只对该表执行删除操作,而不会影响任何模型关系。