Метод explain
Метод explain применяется к QuerySet и возвращает
строку с планом выполнения запроса в формате, зависящем
от используемой базы данных. Этот метод полезен для
диагностики производительности, анализа индексов и
оптимизации сложных запросов. Метод может принимать
параметры, которые передаются в виде ключевых аргументов
и зависят от конкретной СУБД.
Синтаксис
Model.objects.explain(**options)
Пример
Давайте получим план выполнения простого запроса к статьям со статусом "published":
from myapp.models import Article
res = Article.objects.filter(status="published").explain()
print(res)
Результат выполнения кода:
"Seq Scan on app_article (cost=0.00..35.50 rows=1 width=544)
Filter: ((status)::text = 'published'::text)"
Пример
Давайте получим план выполнения запроса с анализом индексов для статей, созданных после первого января две тысячи двадцать пятого года:
from myapp.models import Article
from datetime import date
res = Article.objects.filter(
created_at__date__gte=date(2025, 1, 1)
).explain(verbose=True)
print(res)
Результат выполнения кода:
"Index Scan using app_article_created_at_idx on app_article (cost=0.28..13.57 rows=10 width=544)
Index Cond: (created_at >= '2025-01-01'::date)"
Пример
Давайте проанализируем сложный запрос с объединением таблиц и агрегацией:
from myapp.models import Article, Category
from django.db.models import Count
res = Article.objects.select_related("category").annotate(
category_articles=Count("category__article")
).filter(
category__name__icontains="tech"
).explain(verbose=True, analyze=True)
print(res)
Результат выполнения кода:
"Nested Loop Left Join (cost=18.25..45.87 rows=5 width=116) (actual time=0.035..0.045 rows=3 loops=1)
-> Seq Scan on app_category (cost=0.00..22.50 rows=5 width=4) (actual time=0.012..0.014 rows=3 loops=1)
Filter: ((name)::text ~~* '%tech%'::text)
-> Bitmap Heap Scan on app_article (cost=4.65..14.87 rows=3 width=112) (actual time=0.008..0.009 rows=1 loops=3)
Recheck Cond: (category_id = app_category.id)"