【发布时间】:2021-11-15 23:11:05
【问题描述】:
如何使用 Django 有效地迭代大型查询集(数百万条记录)?
我正在尝试删除几百万条记录,这是我无法使用简单的批量 SQL DELETE 语句执行的操作,因为该事务会消耗过多的服务器内存。所以我正在尝试编写一个 Python 脚本来将大约 10000 个单独的 DELETE 语句分组到一个事务中。
我的脚本如下:
from django.db import transaction
from django.conf import settings
settings.DEBUG = False
qs = MyModel.objects.filter(some_criteria=123)
total = qs.count()
i = 0
transaction.set_autocommit(False)
for record in qs.iterator():
i += 1
if i == 1 or not i % 100 or i == total:
print('%i of %i %.02f%%: %s' % (i + 1, total, (i + 1) / float(total) * 100, record))
record.delete()
if not i % 1000:
transaction.commit()
transaction.commit()
前 2000 条记录运行良好,但随后出现以下错误:
Traceback (most recent call last):
File "/project/.env/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1512, in cursor_iter
for rows in iter((lambda: cursor.fetchmany(itersize)), sentinel):
File "/project/.env/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1512, in <lambda>
for rows in iter((lambda: cursor.fetchmany(itersize)), sentinel):
File "/project/.env/lib/python3.7/site-packages/django/db/utils.py", line 96, in inner
return func(*args, **kwargs)
File "/project/.env/lib/python3.7/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/project/.env/lib/python3.7/site-packages/django/db/utils.py", line 96, in inner
return func(*args, **kwargs)
django.db.utils.ProgrammingError: named cursor isn't valid anymore
如何解决此错误?我使用 PostgreSQL 作为我的数据库后端。
Google 发现很少有人遇到此错误,并且没有提到专门针对 Django 的解决方案。我读过将hold=True 添加到光标调用我的修复它,但不清楚如何通过Django 的ORM 进行设置。
我尝试添加一个 try/except 来捕获并继续查询,但这没有奏效。由于回溯甚至不包括我的代码,我不确定是哪一行触发了异常。
【问题讨论】:
标签: python django postgresql