如何加快djangorestframework-bulk插入?

时间:2019-05-22 23:49:52

标签: django-rest-framework

我正在使用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. RelatedField.run_validation(fk1)
  2. RelatedField.run_validation(fk2)
  3. qs_existsvalidators.py(TheObj)
  4. 插入(TheObj)

但是查询1-3并不是很有用,因为数据库已经对它们进行了检查。 1和2具有外键约束,3具有唯一性约束。

好吧,1和2至少需要运行一次,但是如果它们共享fk对象,则在使用预取的情况下应该将结果缓存起来,但似乎不是。

所以我有两个详细的问题:

  1. 如何让djangorestframework不发出无用的查询#1-3?
  2. 如何让djangorestframework-bulk发行一个插入而不是100个插入?

一次插入一个大块是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

似乎更需要外键查找,但是我在预取和缓存方面遇到了麻烦。

0 个答案:

没有答案