Django Rest Framework разбиение на страницы чрезвычайно медленное количество
Я включил разбиение на страницы в Django Rest framework, и это кажется невероятно медленным. Count выглядит как виновник и занимает сотни миллисекунд, чтобы вернуться каждый раз из-за миллионов строк в таблицах.
Я использую PostgreSQL в качестве базы данных. Есть ли способ не считать строки и по-прежнему использовать разбиение на страницы? Производительность была прекрасной, прежде чем это было включено, если я вручную отфильтровал queryset.
3 ответов
переопределить get_paginated_response
метод вашего класса разбиения на страницы и не включайте счетчик. Вы можете обратиться к реализация базы на PageNumberPagination
класс, чтобы увидеть, что вы должны вернуться.
from rest_framework.pagination import PageNumberPagination
from collections import OrderedDict # requires Python 2.7 or later
class PageNumberPaginationWithoutCount(PageNumberPagination):
# Set any other options you want here like page_size
def get_paginated_response(self, data):
return Response(OrderedDict([
('next', self.get_next_link()),
('previous', self.get_previous_link()),
('results', data)
]))
затем в settings.py
, set DEFAULT_PAGINATION_CLASS
к вашему новому классу разбиения на страницы.
DEFAULT_PAGINATION_CLASS = 'path.to.PageNumberPaginationWithoutCount'
этот подход используется в пример в документах разбиения на страницы.
Edit: из комментариев ниже это звучит так: недостаточно, чтобы предотвратить медленный sql-запрос, поэтому вам может потребоваться переопределить paginate_queryset
как хорошо.
Если вы в порядке без подсчета, следующие и предыдущие ссылки, можно использовать следующий пользовательский класс.
import sys
from collections import OrderedDict
from django.core.paginator import Paginator
from django.utils.functional import cached_property
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
class CustomPaginatorClass(Paginator):
@cached_property
def count(self):
return sys.maxsize
# To Avoid large table count query, We can use this paginator class
class LargeTablePagination(PageNumberPagination):
django_paginator_class = CustomPaginatorClass
def get_paginated_response(self, data):
return Response(OrderedDict([
('page', self.page.number),
('results', data)
]))
проблема в том, что запрос, используемый для подсчета, является тем же потенциально сложным, что и для извлечения данных. Это расточительно. PageNumberPagination
использует собственный Django Paginator
внутренне.
чтобы сделать запрос для count проще переопределить класс paginator DRF использует:
from django.core.paginator import Paginator
from django.utils.functional import cached_property
from rest_framework.pagination import PageNumberPagination
class FasterDjangoPaginator(Paginator):
@cached_property
def count(self):
# only select 'id' for counting, much cheaper
return self.object_list.values('id').count()
class FasterPageNumberPagination(PageNumberPagination):
django_paginator_class = FasterDjangoPaginator