Сегодняшняя тема для обсуждения — вызывает ли request.session.get() в Django снижение производительности? 🎯
При разработке на Django мы часто вызываем request.session.get('key_name')
, верно? Но меня осенило:
"Поскольку сессии в конечном итоге хранятся в БД, происходит ли запрос к БД каждый раз, когда мы вызываем
request.session.get()
?""Или Django каким-то образом умело обрабатывает это так, что дополнительных запросов не возникает?"
Чтобы прояснить этот вопрос, я углубился в исходный код SessionMiddleware Django и провел эксперимент. 🚀
1️⃣ Как Django создает request.session?
Давайте разберемся, когда Django загружает сессии, когда создает объект запроса.
Обычно мы получаем данные сессии в функции представления следующим образом.
session_username = request.session.get('username')
Но если request.session.get('username')
вызывает запрос к БД каждый раз, это может существенно повлиять на производительность, верно?
🔍 Давайте взглянем на внутренности Django!
На самом деле, Django загружает данные сессий заранее через промежуточное программное обеспечение, называемое SessionMiddleware
, когда поступает запрос. На этом этапе происходит только один запрос к БД, а затем данные сессии остаются в объекте request.
В коде SessionMiddleware
Django наблюдается следующее:
class SessionMiddleware(MiddlewareMixin):
def process_request(self, request):
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
request.session = self.SessionStore(session_key)
📌 Важно запомнить!
- ✅ Мы получаем ключ сессии (
session_key
) изrequest.COOKIES
. - ✅ Вызывая
self.SessionStore(session_key)
, мы загружаем данные сессии один раз из БД и сохраняем их в request.session. - ✅ Таким образом, даже если мы многократно вызываем
request.session.get()
в функции представления, дополнительных запросов к БД не происходит! 🎯
2️⃣ Вызывает ли request.session.get() запросы к БД?
Вернемся к главному вопросу.
"Вызывает ли запрос к БД вызов
request.session.get('username')
в представлении?"
🚀 Если сказать кратко, вызов request.session.get()
не приводит к дополнительным запросам к БД.
Причина проста.
✔ Django один раз загружает данные сессий при поступлении запроса и сохраняет их в request.session
.
✔ Следующие вызовы request.session.get()
просто извлекают данные, уже загруженные в память, и дополнительные запросы к БД не нужны.
На самом деле запросы к БД происходят только один раз в начале запроса. SQL-запросы, которые исполняются в этот момент, выглядят так:
SELECT session_data FROM django_session WHERE session_key = 'xyz123' LIMIT 1;
Таким образом, ✅ даже если мы многократно вызываем request.session.get()
в представлении, Django не выполняет дополнительных запросов к БД!
✅ Запрос к БД выполняется только один раз, когда данные загружаются при первом запросе!
3️⃣ Возникают ли запросы при использовании данных сессии в шаблонах?
"Если мы передаем данные сессии из представления в шаблон, и затем используем их там, возникают ли дополнительные запросы к БД?"
Предположим, что мы передаем данные сессии в представление следующим образом:
def my_view(request):
session_username = request.session.get('username') # Запрос к БД? ❌
return render(request, 'my_template.html', {'session_username': session_username})
А затем используем их в шаблоне:
<p>Вход как: {{ session_username }}</p>
В этом случае также не возникает дополнительных запросов к БД!
✔ session_username
— это значение, уже полученное из request.session, поэтому при передаче в шаблон никаких дополнительных запросов к БД не требуется.
✔ Django управляет request.session
как кэш в памяти, поэтому его можно безопасно использовать в шаблонах.
4️⃣ Если изменить данные сессии, будут ли они сохранены в БД?
"А если я изменю данные, например так: request.session['username'] = 'new_value'?"
🚀 В этом случае изменения будут сохранены в БД, и произойдет дополнительный запрос к БД!
Если, например, мы изменим данные сессии так:
request.session['username'] = 'new_value'
Django сохранит измененные данные сессии в БД при отправке ответа. SQL-запрос, который будет выполнен, выглядит следующим образом:
UPDATE django_session SET session_data = 'new_value' WHERE session_key = 'xyz123';
✔ Чтение сессии не вызывает запросов к БД, но изменение сессии приводит к выполнению запросов для сохранения в БД.
5️⃣ Различия в способах хранения сессий (бэкенда)
Дjango позволяет изменять способ хранения сессий (бэкенд). Необходимо учитывать, что в зависимости от бэкенда могут различаться запросы.
Бэкенд сессий | Описание | Запросы к БД |
---|---|---|
django.contrib.sessions.backends.db |
Сессии на основе БД по умолчанию | ✅ Один раз при запросе |
django.contrib.sessions.backends.cache |
Сессии, основанные на кэше (Redis, Memcached) | ❌ Без запросов к БД |
django.contrib.sessions.backends.cached_db |
Кэш + БД сессии (если нет кэша, то запрос к БД) | 🚀 Запрос, если нет в кэше |
django.contrib.sessions.backends.signed_cookies |
Сессии на основе cookies | ❌ Без запросов к БД |
🚀 Таким образом, использованием cache
или signed_cookies
бэкендов позволяет работать с сессиями без запросов к БД. ✔ В случаях, когда производительность критична, рассмотрение CACHED_DB_SESSION
может быть отличным вариантом.
🎯 Заключение
- ✅ Django загружает данные сессий заранее через
SessionMiddleware
, сохраняя их вrequest.session
. - ✅ Следовательно, вызов
request.session.get('username')
в представлении не приводит к дополнительным запросам к БД. - ✅ Во время использования данных сессий в шаблонах тоже не возникают дополнительные запросы к БД.
- ✅ Однако, если изменить значение сессии, Django сохранит измененное значение в БД, когда отправляет ответ.
- ✅ В соответствии с настройками бэкенда сессий возникновение запросов может различаться, использование кэшированных (например,
cache
илиcached_db
) вариантов помогает уменьшить нагрузку на БД.
🔥 Анонс следующего выпуска: когда исчезает объект request
?
Итак, когда исчезает объект request
?
-
Продолжает ли он занимать память даже после завершения запроса?
-
Очищается ли автоматически системой или нам нужно убирать его самостоятельно?
🚀 В следующем выпуске мы исследуем жизненный цикл объекта request
в Django и управление памятью! Ожидайте с нетерпением! 😃
댓글이 없습니다.