В этом разделе мы рассмотрим оптимизацию SQL запросов Django ORM с помощью select_related(), используя менеджер и Django Debug Toolbar. Так же будет показано решение проблем с запросами N+1 в Django.
Проблема n+1 (или проблема "жадной" загрузки) - это частое явление при использовании ORM, когда при попытке загрузить данные из связанных таблиц происходит множественный запрос к базе данных вместо одного оптимизированного запроса.
Для начала установим Django Debug Toolbar:
pip install django-debug-toolbar
Далее в файл настроек добавим следующий код:
INTERNAL_IPS = [
'127.0.0.1', # New
]
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'apps.blog.apps.BlogConfig',
'mptt',
'django_mptt_admin',
'debug_toolbar', # приложение тулбара
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware', # Middleware тулбара
]
Django Debug Toolbar отображается только в том случае, если в списке INTERNAL_IPS есть IP приложения. Для разработки на локальном компьютере мы добавляем в список IP 127.0.0.1.
В случае если появляются проблемы с отображением тулбара, то добавьте следующий код в файл настроек:
def show_toolbar(request):
return True
DEBUG_TOOLBAR_CONFIG = {
"SHOW_TOOLBAR_CALLBACK": show_toolbar,
}
Этот код отключит любые проверки отображения тулбара. Но используйте этот код только для тестирования при локальной разработке, если вы забудете и сделаете деплой проекта с ним, все ваши посетители также увидят вашу панель инструментов отладки.
Теперь необходимо изменить главный urls.py, добавив работу дебагера в режиме отладки DEBUG = True:
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += [path('__debug__/', include('debug_toolbar.urls'))]
Запустим сервер и проверим работу дебагера:
Мы видим что он прекрасно работает, перейдем в раздел SQL и посмотрим запросы:
На данном скриншоте мы можем заметить одинаковые запросы к пользователю, а также к категориям. Это проблема, и называется она N+1. Если бы на странице было бы ещё больше статей, то и запросов SQL было бы пропорционально больше.
В следующем шаге мы попробуем решить эту проблему.