Последнее время я заметил, что близится тот роковой момент, когда ккатастрофически перестанет хватать дискового пространства для сайта на хостинге. А дамп базы данных становится невероятно огромным, хотя очевидных предпосылок для этого никаких нет. Размер контента на сайте не растёт так быстро, да и количество зарегистрированных пользователей также не прибывает так быстро.
После изучения базы данных было обнаружено, что размер таблицы django_session просто гигантский почти 7 Гб, а размер индекса тоже достигает почти 6.5 Гб, при том, что размер самой базы данных 14 Гб.
При этом размер второй по величине таблицы всего 11 Мб и это стороннее приложение со списком городов. А размер третьей таблицы, которая содержит сообщения на форуме всего 8 Мб.
Соответственно было решено разобраться, почему это происходит и как исправлять.
Сейчас я скорее всего не открою ничего нового для тех, кто активно администрирует базы данных на PostgreSQL, но для новичков и тех, кто в основном занимается Django в качестве PET проекта, без профессионального использования, информация может быть полезной.
Как проверить размер таблицы
https://evileg.com/ru/knowledge/article/add/#
Для этого достаточно выполнить следующий запрос в интерфейсе администрирования PostreSQL. И получим отсортированный вывод информации по таблицам базы данных.
select table_name, pg_relation_size(quote_ident(table_name)), pg_size_pretty(pg_relation_size(quote_ident(table_name))) from information_schema.tables where table_schema = 'public' order by 2; forum_forumpost | 8290304 | 8096 kB cities_light_city | 11108352 | 11 MB django_session | 7225204736 | 6890 MB (110 rows)
Как видите, в моём случае таблица djang_session за 6 лет существования сайта на движке Django разрослась очень сильно.
Спасибо DDOS посетителям, механизму создания ключей сессии для всех анонимных пользователей, а также тому, что по умолчанию PostgreSQL даже при удалении записей не уменьшает размер файла базы данных.
А размер базы данных можно посмотреть так
SELECT pg_size_pretty( pg_database_size('databasename') ); pg_size_pretty ---------------- 14 GB (1 row)
Вот такой неприятный размерчик вышел - 14 GB.
Удаление сессий с истёкшим сроком
Когда сайт подвергается DDOS или просто наплыву пользователей, то создаётся огромное число сессий, которые обычно в Django не удаляются, а также дополнительно растёт индекс таблицы.
Поэтому первое, что нужно сделать, это удалить устаревшие сессии. Для этого в Django есть команда clearsessions .
Поэтому в консоли активируем python среду вашего проекта, переходим в папку с вашим проектом и выполняем следующую команду.
python manage.py clearsessions
Это удалит все старые сессии. Вы также можете настроить выполнение этой команды по расписанию через cron.
Например с помощью батарейки
django-session-cleanup
, для неё необходимо использование
celery
.
Запуск сборщика мусора
После того, как вы выполнили удаление старых сессий, вам необходимо освободить пространство занятое базой данных.
Это необходимо потому, что приоритет базы данных - это производительность, а не экономия дискового пространства. Таким образом файл базы данных разрастается за счёт роста индекса, а данных там уже давно нет. А также по умолчанию сборщик мусора не запускается сам по себе, для этого необходимо настраиваеть его запуск по расписанию, например с помощью демона.
Но лично я пока сделал это вручную. Сборщик мусора в PostgreSQL запускается командой vacuum .
vacuum FULL ANALYZE django_session;
После выполнения этой операции снова проверяю размер базы данных и вижу
SELECT pg_size_pretty( pg_database_size('databasename') ); pg_size_pretty ---------------- 494 MB (1 row)
Теперь размер базы данных всего 494 MB, что не может не радовать.
Надо будет со временем настроить запуск сборщика мусора хотя бы раз в неделю, но об этом уже в следующей статье.
А если хранить сессии в SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' ?
Интересно стало насколько безопасно хранить сессии в печеньках... стоит оно того или нет?)
Думаю, что скорее всего это будет менее безопасно, но на практике я не проверял.