Включение некоторых записей в SQL-запрос увеличивает время выполнения запроса в пять раз на Heroku
Мы используем Django с django-guardian для объектно-ориентированных разрешений. Недавно мы столкнулись с экстремальным увеличением времени выполнения определенного запроса, по крайней мере, для одного пользователя с большим количеством annotation_texthighlight
. Вот запрос:
SELECT "annotation_texthighlight"."uuid",
[omitted for readability]
FROM "annotation_texthighlight"
INNER JOIN "annotation_annotation"
ON ("annotation_texthighlight"."annotation_id" = "annotation_annotation"."uuid")
WHERE (
"annotation_texthighlight"."annotation_id" IN
(SELECT U0."uuid"
FROM "annotation_annotation" U0
WHERE (U0."chapter_id" =
'9a481c82-c44b-4ead-94bb-48de0910877b'::uuid AND
U0."min_revision_id" IN
('5a301886-e200-441f-ad8e-03c4eb9bd773'::uuid,
'6f539d6f-c9eb-41e2-956e-32b4a5950c33'::uuid))) AND
"annotation_texthighlight"."uuid" IN
(SELECT CAST(U0."object_pk" AS uuid) AS "obj_pk"
FROM "guardian_userobjectpermission" U0
INNER JOIN "auth_permission" U2 ON (U0."permission_id" = U2."id")
WHERE (U0."user_id" = 1522 AND U2."content_type_id" = 89 AND
U2."codename" IN ('view_texthighlight')))
);
Это меня очень озадачило. Вот результаты моего расследования на данный момент:
- Копирование базы данных с исходного Heroku (Postgres 13.4, standard-2, 4GB RAM, 1.2 GB DB size) на локальный (стоковый Postgres 13 через стандартный образ Docker) сократит время выполнения на ~250ms.
- Всего будет возвращено около 1200 записей. Первые 700 (
LIMIT 700
) займут ~5 секунд. Остальные (OFFSET 700 LIMIT 700
) займут ~25 секунд. - Устранение любого из фильтров
WHERE
сократит время выполнения <1 с.
Мое лучшее предположение - это другая конфигурация на Heroku по сравнению с Docker-образом Postgres по умолчанию.