django
的orm提供bulk_update
批量更新记录的方法,
bulk_update(self, objs, fields, batch_size=None)
这里有个batch_size
参数,作用是在待更新的objs数量过大时,提供分批更新的功能。
那么是怎么实现的呢?
很容易想到的是,对objs进行切片,每次取batch_size
大小,然后对每个切片循环添加到update数组里。
那么django
的源码是怎么做的呢?
我们在django\db\models\query.py
中可以看到:
def bulk_update(self, objs, fields, batch_size=None):
"""
Update the given fields in each of the given objects in the database.
"""
······
······
max_batch_size = connections[self.db].ops.bulk_batch_size(['pk', 'pk'] + fields, objs)
batch_size = min(batch_size, max_batch_size) if batch_size else max_batch_size
requires_casting = connections[self.db].features.requires_casted_case_in_updates
batches = (objs[i:i + batch_size] for i in range(0, len(objs), batch_size))
updates = []
for batch_objs in batches:
······
updates.append(([obj.pk for obj in batch_objs], update_kwargs))
······
这里最核心的代码是这一句:
batches = (objs[i:i + batch_size] for i in range(0, len(objs), batch_size))
初看这段代码有点奇怪,这里是怎么实现分批更新的呢,就在这里,这里batches是一个生成器generator
只需要把一个列表生成式的[]
改成()
就可以创建一个生成器,这样我们无需把完整的objs按照batch_size
分割成一个个切片执行update,而是直接对batches
循环就可以源源不断生成list。
我们在遇到类似场景时可以借鉴这种技巧。