Django: SQL-запросы выполняются медленно из-за сложных подзапросов, как их разделить или ускорить?
Мне нужно выполнить набор запросов со сложными подзапросами, как показано ниже. Выполнение запроса занимает значительное время. (8000 мс)
Я думаю, что замедление вызвано сложными подзапросами, но возможно ли разделить или ускорить один SQL-запрос без генерации N+1?
Используемый нами поиск в базе данных и медленный набор запросов в этот раз
# lookups.py
class Groonga(Lookup):
lookup_name = "groonga"
def as_sql(self, compiler, connection):
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
params = lhs_params + rhs_params
return "%s &@~ %s" % (lhs, rhs), params
# queryset
Video.objects.annotate(
is_viewed=Exists(History.objects.filter(user=user, video=OuterRef("pk"))),
is_favorited=Exists(
Favorite.objects.filter(user=user, video=OuterRef("pk"))
),
is_wl=Exists(
Track.objects.filter(
playlist__user=user, playlist__is_wl=True, video=OuterRef("pk")
)
),
).filter(
Q(title__groonga=value)
| Q(tags__pk__in=Tag.objects.filter(name__groonga=value).values_list("pk")),
is_public=True,
published_at__lte=timezone.now(),
).order_by("-published_at").distinct()[:20]
SQL запрос и результаты EXPLAIN ANALYZE
Вы можете иметь сложные подзапросы, но это не первая атака, необходимая для лучшего выполнения. Вот виновник: Sort Method: external merge Disk: 12232kB
. Вы выполняете сортировку на ДИСКЕ, а не в памяти. Вам нужно увеличить work_mem.
work_mem (целое число)
Устанавливает базовый максимальный объем памяти, который будет использоваться операцией запроса > (такой как сортировка или хэш-таблица) перед записью во временные дисковые файлы.