Django-rest-framework 性能问题

Django-rest-framework performance issues

大家好,这是我的观点class

class ModuleViewSet(mixins.CreateModelMixin,
                    mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.ListModelMixin,
                    viewsets.GenericViewSet):
    queryset = models.Module.objects.all()
    permission_classes = [ModuleViewPermission]
    serializer_class = serializers.ModuleSerializer

我已将 django.db 记录器设置为 INFO 级别,以查看正在执行的实际数据库查询。以下是我的发现:

  1. 获取模块列表:
2020-07-26 19:22:18,062 DEBUG utils:110 e70f16f5c7494c8783ca9f5a6bea22c4 (0.013) SELECT "courses_module"."id", "courses_module"."course_id", "courses_module"."name", "courses_module"."number" FROM "courses_module"; args=() django.db.backends
2020-07-26 19:22:18,090 INFO basehttp:154 e70f16f5c7494c8783ca9f5a6bea22c4 "GET /api/courses/modules/ HTTP/1.1" 200 99 django.server
  1. 获取单个对象:
2020-07-26 19:23:26,143 DEBUG utils:110 f1332e4a5e2247709dc784dc2f8b6d19 (0.005) SELECT "courses_module"."id", "courses_module"."course_id", "courses_module"."name", "courses_module"."number" FROM "courses_module"; args=() django.db.backends
2020-07-26 19:23:27,331 DEBUG utils:110 f1332e4a5e2247709dc784dc2f8b6d19 (0.003) SELECT "courses_module"."id", "courses_module"."course_id", "courses_module"."name", "courses_module"."number" FROM "courses_module" WHERE "courses_module"."id" = 1; args=(1,) django.db.backends
2020-07-26 19:23:27,342 DEBUG utils:110 f1332e4a5e2247709dc784dc2f8b6d19 (0.006) SELECT "courses_course"."id", "courses_course"."name", "courses_course"."description", "courses_course"."price_group_id" FROM "courses_course" WHERE "courses_course"."id" = 1; args=(1,) django.db.backends
2020-07-26 19:23:27,359 DEBUG utils:110 f1332e4a5e2247709dc784dc2f8b6d19 (0.015) SELECT "user_user"."id", "user_user"."password", "user_user"."last_login", "user_user"."is_superuser", "user_user"."username", "user_user"."is_staff", "user_user"."is_active", "user_user"."date_joined", "user_user"."email", "user_user"."first_name", "user_user"."last_name" FROM "user_user" INNER JOIN "courses_course_authors" ON ("user_user"."id" = "courses_course_authors"."user_id") WHERE "courses_course_authors"."course_id" = 1; args=(1,) django.db.backends
2020-07-26 19:23:27,375 INFO basehttp:154 f1332e4a5e2247709dc784dc2f8b6d19 "GET /api/courses/modules/1/ HTTP/1.1" 200 45 django.server

对于 1,select 可能是正确的,但根据文档查询集是 cached for the upcoming requests. But in get_queryset() method we can see that we are re-evaluating queryset

除了这个矛盾。 获取单个对象(第 2 部分)的结果更令人担忧。因为我们首先 selecting 所有对象,然后再次 selecting 通过 Id 的模块对象。最后 2 个查询用于检查用户对该对象的权限(acceptable)。

如果我的观点有误,或者这是 django rest 框架的已知性能问题,请告诉我。也提过这个问题here

如果 table 中有数百万条记录,这可能是一个主要问题。

谢谢

我找到了这种杂项行为背后的原因。查询集是惰性的,只要我们期望结果就会计算它们。当我调试并将鼠标悬停在查询集上时,查询正在按照调试器预期的结果执行。我可能是错的。但是当我在非调试模式下 运行 时,我无法重现上面的输出。以下是日志: 获取列表:


2020-07-26 23:00:06,697 DEBUG utils:110 1c8a250d8f784aff9c4e5056e446ddf9 (0.004) SELECT "courses_module"."id", "courses_module"."course_id", "courses_module"."name", "courses_module"."number" FROM "courses_module"; args=() django.db.backends
2020-07-26 23:00:06,706 INFO basehttp:154 1c8a250d8f784aff9c4e5056e446ddf9 "GET /api/courses/modules/ HTTP/1.1" 200 99 django.server

获取对象:

2020-07-26 22:59:47,120 DEBUG utils:110 018f23ade3774a44a7cd423c80f6fe59 (0.005) SELECT "courses_module"."id", "courses_module"."course_id", "courses_module"."name", "courses_module"."number" FROM "courses_module" WHERE "courses_module"."id" = 1; args=(1,) django.db.backends
2020-07-26 22:59:47,125 DEBUG utils:110 018f23ade3774a44a7cd423c80f6fe59 (0.004) SELECT "courses_course"."id", "courses_course"."name", "courses_course"."description", "courses_course"."price_group_id" FROM "courses_course" WHERE "courses_course"."id" = 1; args=(1,) django.db.backends
2020-07-26 22:59:47,137 DEBUG utils:110 018f23ade3774a44a7cd423c80f6fe59 (0.011) SELECT "user_user"."id", "user_user"."password", "user_user"."last_login", "user_user"."is_superuser", "user_user"."username", "user_user"."is_staff", "user_user"."is_active", "user_user"."date_joined", "user_user"."email", "user_user"."first_name", "user_user"."last_name" FROM "user_user" INNER JOIN "courses_course_authors" ON ("user_user"."id" = "courses_course_authors"."user_id") WHERE "courses_course_authors"."course_id" = 1; args=(1,) django.db.backends
2020-07-26 22:59:47,168 INFO basehttp:154 018f23ade3774a44a7cd423c80f6fe59 "GET /api/courses/modules/1/ HTTP/1.1" 200 45 django.server

仍未确认 1(list) 的查询集缓存。现在我们可以使用 2.

谢谢 阿尼克特