我正在使用djangorestframework 3.9.2和djangorestframework-bulk 0.2.1。我正在尝试通过REST POST插入100个对象,并且它提交的查询过多。详细信息如下。
模型对象:
class TheObj(models.Model):
fk1 = models.ForeignKey(Foreign1, models.DO_NOTHING, blank=False, null=False)
fk2 = models.ForeignKey(Foreign2, models.DO_NOTHING, blank=False, null=False)
data = models.IntegerField(blank=False, null=False)
# more data here ..
序列化器和视图集:
class TheObjSerializer(serializers.ModelSerializer,
BulkSerializerMixin,
BulkCreateModelMixin):
class Meta:
model = TheObj
fields = '__all__'
list_serializer_class = BulkListSerializer
@staticmethod
def setup_eager_loading(queryset):
queryset = queryset.select_related('fk1')
return queryset.select_related('fk2')
class TheObjResultViewSet(BulkModelViewSet):
queryset = TheObj.objects.all()
serializer_class = TheObjSerializer
def get_queryset(self):
queryset = TheObj.objects.all()
# Set up eager loading to avoid N+1 selects
return self.get_serializer_class().setup_eager_loading(queryset)
如果我通过批量REST调用(数据为100个对象的数组的REST调用)插入100个对象,则每个对象发出4个调用:
但是查询1-3并不是很有用,因为数据库已经对它们进行了检查。 1和2具有外键约束,3具有唯一性约束。
好吧,1和2至少需要运行一次,但是如果它们共享fk对象,则在使用预取的情况下应该将结果缓存起来,但似乎不是。
所以我有两个详细的问题:
一次插入一个大块是0.2秒。当前速度约为30秒。太残忍了。
我已经读过this,预取似乎无济于事(上面的setup_eager_loading)。
我尝试不使用setup_eager_loading。我试过不使用BulkSerializerMixin或BulkCreateModelMixin或BulkListSerializer。
我尝试了多种组合。
也许我需要在序列化程序中设置不同的外键?
对于#2,我是否必须在某个地方获得很多= True?
欢迎您。
编辑:通过将查询添加到TheObjSerializer中,我能够删除其中一个查询(unique_together验证):
def run_validators(self, value):
"""For speed, don't run serializer validation. Let the DB validate."""
pass
似乎更需要外键查找,但是我在预取和缓存方面遇到了麻烦。