Django queryset iterator() 没有按预期工作

Django queryset iterator() doesn't work as expected

我已经根据 Django 文档测试 queryset.iterator()

Oracle and PostgreSQL use server-side cursors to stream results from the database without loading the entire result set into memory.

With server-side cursors, the chunk_size parameter specifies the number of results to cache at the database driver level. Fetching bigger chunks diminishes the number of round trips between the database driver and the database, at the expense of memory.

On PostgreSQL, server-side cursors will only be used when the DISABLE_SERVER_SIDE_CURSORS setting is 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()的理解有误吗?

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

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

要从游标中获取数据,应首先打开游标(使用 OPEN statement) and then data should be fetched (using FETCH 语句)。

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