我有大约一百万条 Comment
记录,我想根据该评论的 body
字段更新这些记录。我正在尝试找出如何有效地做到这一点。现在,我的方法如下:
update_list = []
qs = Comments.objects.filter(word_count=0)
for comment in qs:
model_obj = Comments.objects.get(id=comment.id)
model_obj.word_count = len(model_obj.body.split())
update_list.append(model_obj)
Comment.objects.bulk_update(update_list, ['word_count'])
但是,这在我的迁移过程中挂起并且似乎超时。有人对我如何实现这一目标有建议吗?
最佳答案
确定 Django 对象的内存占用量并不容易,但绝对最小值是存储其所有数据所需的空间量。我的猜测是,您可能会耗尽内存并出现页面抖动。
您可能希望一次批量处理(例如 1000 个对象)。使用Queryset slicing ,它返回另一个查询集。尝试类似的事情
BATCH_SIZE = 1000
start = 0
base_qs = Comments.objects.filter(word_count=0)
while True:
batch_qs = base_qs[ start: start+BATCH_SIZE ]
start += BATCH_SIZE
if not batch_qs.exists():
break
update_list = []
for comment in batch_qs:
model_obj = Comments.objects.get(id=comment.id)
model_obj.word_count = len(model_obj.body.split())
update_list.append(model_obj)
Comment.objects.bulk_update(update_list, ['word_count'])
print( f'Processed batch starting at {start}' )
循环中的每一次替换batch_qs和update_list时都会释放前一次所占用的空间。打印语句将允许您以希望可以接受的正常速度观察它的进展!
警告 - 我从未尝试过这个。我还想知道切片和过滤是否可以很好地配合,或者是否应该使用
base_qs = Comments.objects.all()
...
while True:
batch_qs = base_qs[ start: start+BATCH_SIZE ]
....
for comment in batch_qs.filter(word_count=0) :
因此,您可以对整个数据库表中的行进行切片,并检索需要更新的每个切片的子集。这感觉“更安全”。有人确切知道吗?
关于django - 使用 Django 根据记录中的字段高效更新大量记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71269858/