2017-06-20 45 views
0

以下のシリアライザセットを使用して、開発環境で正常に動作する結合を実現していますが、ウェブサイトサーバとデータベースサーバの間に距離がある場合は非常に優れています。私はショーを実行しているSQLについて疑念を持ち、いくつかのログをとった。それはすべてのエントリのための新しいクエリをやっていると思うのですが、一度に結合全体を行い、望むように結合を返すのではなく、結果を結合するようです。ここに私のシリアライザは、以下のとおりです。Django REST Frameworkシリアライザを使用した効率的な結合

class UserSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = User 
     exclude = ('password', 'last_login', 'is_superuser', 'is_staff', 'is_active', 'date_joined', 
        'groups', 'user_permissions') 


class DepartmentSerializer(serializers.HyperlinkedModelSerializer): 
    curator = UserSerializer() 
    class Meta: 
     model = Department 
     fields = '__all__' 


class CategorySerializer(serializers.HyperlinkedModelSerializer): 
    class Meta: 
     model = Category 
     fields = '__all__' 


class DetailedLinkedContentSerializer(serializers.HyperlinkedModelSerializer): 
    category = CategorySerializer() 
    department = DepartmentSerializer() 
    type = serializers.SerializerMethodField() 

    class Meta: 
     fields = '__all__' 
     model = LinkedContent 

    def get_type(self, obj): 
     return 'link' 


class DetailedFileContentSerializer(serializers.HyperlinkedModelSerializer): 
    category = CategorySerializer() 
    department = DepartmentSerializer() 
    link_url = serializers.SerializerMethodField() 
    type = serializers.SerializerMethodField() 

    class Meta: 
     fields = '__all__' 
     model = FileContent 

    def get_link_url(self, obj): 
     return obj.file.url 

    def get_type(self, obj): 
     return obj.file_type 

あなたが見ることができるように、私は私がそのようなカテゴリ= CategorySerializer()などの他のモデルのシリアライザとしてシリアライザのフィールドを含むことにより、「参加」やっています。私が何かを誤解していない限り、それはDRF recommendsのように見えます。ここに私の開発環境上で実行されてクエリの数百と何百もの小さなサンプルです:

(0.001) SELECT "content_linkedcontent"."id", "content_linkedcontent"."link_text", "content_linkedcontent"."department_id", "content_linkedcontent"."category_id", "content_linkedcontent"."visibility_rank", "content_linkedcontent"."link_url" FROM "content_linkedcontent"; args=() 
(0.001) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 3; args=(3,) 
(0.001) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 24; args=(24,) 
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 3; args=(3,) 
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 3; args=(3,) 
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 29; args=(29,) 
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,) 
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 4; args=(4,) 
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 25; args=(25,) 
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,) 
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 1; args=(1,) 
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 29; args=(29,) 
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,) 
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 1; args=(1,) 
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 25; args=(25,) 
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,) 
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 1; args=(1,) 
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 24; args=(24,) 
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 3; args=(3,) 
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 3; args=(3,) 
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 28; args=(28,) 
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,) 
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 1; args=(1,) 
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 28; args=(28,) 
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,) 
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 4; args=(4,) 

は、どのように私は私がDRFでシリアライザを使用したい情報をリアルに参加できますか?

UPDATE:

私はここに、thisブログエントリのアドバイスに従うことによって半分にクエリ時間を削減するために管理してきたが、私の更新シリアライザおよびそれらを使用する図である。

class DetailedLinkedContentSerializer(serializers.HyperlinkedModelSerializer): 
    category = CategorySerializer() 
    department_query = Department.objects.all() 
    department_query = DepartmentSerializer.setup_eager_loading(department_query) 
    department = DepartmentSerializer(department_query) 
    # department = DepartmentSerializer() 
    type = serializers.SerializerMethodField() 

    class Meta: 
     fields = '__all__' 
     model = LinkedContent 

    def get_type(self, obj): 
     return 'link' 

    @staticmethod 
    def setup_eager_loading(queryset): 
     """ Perform necessary eager loading of data. """ 
     queryset = queryset.select_related('category', 'department') 
     return queryset 


class DetailedFileContentSerializer(serializers.HyperlinkedModelSerializer): 
    category = CategorySerializer() 
    department_query = Department.objects.all() 
    department_query = DepartmentSerializer.setup_eager_loading(department_query) 
    department = DepartmentSerializer(department_query) 
    # department = DepartmentSerializer() 
    link_url = serializers.SerializerMethodField() 
    type = serializers.SerializerMethodField() 

    class Meta: 
     fields = '__all__' 
     model = FileContent 

    def get_link_url(self, obj): 
     return obj.file.url 

    def get_type(self, obj): 
     return obj.file_type 

    @staticmethod 
    def setup_eager_loading(queryset): 
     """ Perform necessary eager loading of data. """ 
     queryset = queryset.select_related('category', 'department') 
     return queryset 

と私これらのシリアライザを使用するビュー:

class DetailedContentView(views.APIView): 
    permission_classes = [IsAuthenticated, ContentCuratorOrReadOnly, IsGroupMember, ] 
    def get(self, request, *args, **kwargs): 
     context = {"request": request} 
     linked_content = LinkedContent.objects.all() 
     file_content = FileContent.objects.all() 
     # this line is newly added 
     linked_content = DetailedLinkedContentSerializer.setup_eager_loading(linked_content) 
     # this line too 
     file_content = DetailedLinkedContentSerializer.setup_eager_loading(file_content) 
     linked_content_serializer = DetailedLinkedContentSerializer(linked_content, many=True, context=context) 
     file_content_serializer = DetailedFileContentSerializer(file_content, many=True, context=context) 

     response = linked_content_serializer.data + file_content_serializer.data 
     response = sorted(response, key=lambda x: (x['department']['visibility_rank'], x['visibility_rank'])) 

     return Response(response) 

しかし、シリアライザ私の部署のシリアライザ以内に私のユーザーをプリフェッチする私の解決策はしていないようですトリックをやっている。具体的に私の部署・シリアライザを更新した後:

class DepartmentSerializer(serializers.HyperlinkedModelSerializer): 
    curator = UserSerializer() 
    class Meta: 
     model = Department 
     fields = '__all__' 

    @staticmethod 
    def setup_eager_loading(queryset): 
     """ Perform necessary eager loading of data. """ 
     queryset = queryset.select_related('curator') 
     return queryset 

次の行:私が望むよう

department_query = Department.objects.all() 
department_query = DepartmentSerializer.setup_eager_loading(department_query) 
department = DepartmentSerializer(department_query) 

は私のキュレーターをプリフェッチしていないようです。

+0

[select_related](https://docs.djangoproject.com/en/1.11/ref/models/querysets/#select-related)または[prefetch_related](https://docs.djangoproject.com)を使用してみましたか?あなたのビューのクエリーセットに/en/1.11/ref/models/querysets/#prefetch-related)これらは、各エントリと各リレーションに対する新しい要求を避けるためにデータをプリロードする必要があります。 –

+0

私はそのことについて現在取り組んでおり、私は質問を更新しようとしています。 – DragonBobZ

答えて

0

私はthis blogで見つかったコメントからのミックスインを使用して、私のシリアライザを更新:

class EagerLoadingMixin: 
    @classmethod 
    def setup_eager_loading(cls, queryset): 
     if hasattr(cls, "_SELECT_RELATED_FIELDS"): 
      queryset = queryset.select_related(*cls._SELECT_RELATED_FIELDS) 
     if hasattr(cls, "_PREFETCH_RELATED_FIELDS"): 
      queryset = queryset.prefetch_related(*cls._PREFETCH_RELATED_FIELDS) 
     return queryset 

とプリフェッチ・フィールドの私のリストに'department__curator'を追加しました。これは次のようになります。

class DetailedFileContentSerializer(EagerLoadingMixin, serializers.HyperlinkedModelSerializer): 
    category = CategorySerializer() 
    department = DepartmentSerializer() 
    link_url = serializers.SerializerMethodField() 
    type = serializers.SerializerMethodField() 

    class Meta: 
     fields = '__all__' 
     model = FileContent 

    def get_link_url(self, obj): 
     return obj.file.url 

    def get_type(self, obj): 
     return obj.file_type 

    _SELECT_RELATED_FIELDS = ['department', 'category', 'department__curator'] 

クエリの時間は約1/3で、何百ものSELECTが含まれていません。それでも時間がかかりますが、私は自分のデータベースのために別のホスティングソリューションに切り替えることで解決できると思います。

関連する問題