Ускорение order_by и пагинации в Django
В настоящее время я имею следующий результат:
Это неплохо (я думаю), но мне интересно, могу ли я немного ускорить процесс.
Я просмотрел предпоследний запрос и не знаю, как его ускорить, я думаю, мне нужно избавиться от join, но не знаю как:
Я уже использую prefetch_related
в своем наборе представлений, мой набор представлений:
class GameViewSet(viewsets.ModelViewSet):
queryset = Game.objects.prefetch_related(
"timestamp",
"fighters",
"score",
"coefs",
"rounds",
"rounds_view",
"rounds_view_f",
"finishes",
"rounds_time",
"round_time",
"time_coef",
"totals",
).all()
serializer_class = GameSerializer
permission_classes = [AllowAny]
pagination_class = StandardResultsSetPagination
@silk_profile(name="Get Games")
def list(self, request):
qs = self.get_queryset().order_by("-timestamp__ts")
page = self.paginate_queryset(qs)
if page is not None:
serializer = GameSerializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(qs, many=True)
return Response(serializer.data)
Соединение происходит потому, что я делаю заказ по связанному полю?
Мои модели выглядят следующим образом:
class Game(models.Model):
id = models.AutoField(primary_key=True)
...
class Timestamp(models.Model):
id = models.AutoField(primary_key=True)
game = models.ForeignKey(Game, related_name="timestamp", on_delete=models.CASCADE)
ts = models.DateTimeField(db_index=True)
time_of_day = models.TimeField()
И мои сериализаторы:
class TimestampSerializer(serializers.Serializer):
ts = serializers.DateTimeField(read_only=True)
time_of_day = serializers.TimeField(read_only=True)
class GameSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
timestamp = TimestampSerializer(many=True)
fighters = FighterSerializer(many=True)
score = ScoreSerializer(many=True)
coefs = CoefsSerializer(many=True)
rounds = RoundsSerializer(many=True)
rounds_view = RoundsViewSerializer(many=True)
rounds_view_f = RoundsViewFinishSerializer(many=True)
finishes = FinishesSerializer(many=True)
rounds_time = RoundTimesSerializer(many=True)
round_time = RoundTimeSerializer(many=True)
time_coef = TimeCoefsSerializer(many=True)
totals = TotalsSerializer(many=True)
Также результаты профилирования:
И визуальное представление:
Итак, мои вопросы: как я могу ускорить это?
На стороне базы данных вы можете создать материализованное представление для вашего запроса и запускать обновление при добавлении новой временной метки (или при любом другом событии в вашем приложении, требующем обновления). Таким образом, результаты будут предварительно рассчитаны для вашего поиска. Однако я полагаю, что могут быть граничные случаи, когда при одновременном обновлении и поиске вы получаете предварительно обновленный результат? Это будет компромисс, и только вы знаете, стоит ли это того...
В любом случае, не я это придумал, посмотрите, например, https://hashrocket.com/blog/posts/materialized-view-strategies-using-postgresql