Django queryset iterator()无法按预期工作

时间:2018-12-27 17:21:21

标签: python django python-3.x postgresql django-2.0

我已经基于Django文档测试了queryset.iterator()

  

Oracle和PostgreSQL使用服务器端游标从数据库流式传输结果,而无需将整个结果集加载到内存中。

     

对于服务器端游标,chunk_size参数指定要在数据库驱动程序级别缓存的结果数。提取更大的块会减少数据库驱动程序和数据库之间的往返次数,但会浪费内存。

     

在PostgreSQL上,仅当DISABLE_SERVER_SIDE_CURSORS设置为False时才使用服务器端游标。

print(settings.DATABASES['default']['ENGINE']) # postgresql

class TestModel(Model):
    age = IntegerField(default=1)

# Insert 10 rows
for i in range(10):
    TestModel().save()

settings.DEBUG = True
l = logging.getLogger('django.db.backends')
l.setLevel(logging.DEBUG)
l.addHandler(logging.StreamHandler())   
# From now, every queries emitted by Django will be printed.    

print(settings.DISABLE_SERVER_SIDE_CURSORS) # False

for i in TestModel.objects.all().iterator(chunk_size=2):
    print(i.age)

(0.001) DECLARE "_django_curs_4369655232_3" NO SCROLL CURSOR WITH HOLD FOR SELECT "testmodel"."age" FROM "testmodel"; args=()

由于chunk_size=2(行总数为10),我希望上面的代码每2行会命中数据库5次。

但是,它似乎只发出一个查询(高于打印查询)。

我对queryset.iterator()有误解吗?

1 个答案:

答案 0 :(得分:1)

您已正确理解queryset.iterator()的用途。

在这种情况下(PostgreSQL),Django声明了一个游标(使用DECLARE语句),该游标应在迭代器内部使用。

要从游标中获取数据,应首先打开游标(使用OPEN语句),然后再获取数据(使用FETCH语句)。

似乎您的日志记录没有捕获到迭代器内部发生的任何这些语句,要确认这一点,您可以在PostgreSQL端设置日志记录:)。