Останнім часом я помітив, що наближається той фатальний момент, коли катастрофічно перестане хапати дискового простору для сайту на хостингу. А дамп бази даних стає неймовірно величезним, хоча очевидних передумов для цього жодних немає. Розмір контенту на сайті не зростає так швидко, та й кількість зареєстрованих користувачів також не прибуває так швидко.
Після вивчення бази даних було виявлено, що розмір таблиці 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' ?
Интересно стало насколько безопасно хранить сессии в печеньках... стоит оно того или нет?)
Думаю, что скорее всего это будет менее безопасно, но на практике я не проверял.