Lately, I have noticed that the fatal moment is approaching, when the disk space for the site on the hosting will catastrophically cease to be enough. And the database dump becomes incredibly huge, although there are no obvious prerequisites for this. The content size of the site isn't growing that fast, and the number of registered users isn't growing that fast either.
After examining the database, it was found that the size of the django_session table is just a gigantic almost 7 GB, and the size of the index also reaches almost 6.5 GB, despite the fact that the size of the database itself is 14 GB.
At the same time, the size of the second largest table is only 11 MB and this is a third-party application with a list of cities. And the size of the third table, which contains messages on the forum, is only 8 MB.
Accordingly, it was decided to figure out why this is happening and how to fix it.
Right now, I probably won’t reveal anything new to those who actively administer PostgreSQL databases, but for beginners and those who mainly deal with Django as a PET project, without professional use, the information may be useful.
How to check table size
To do this, simply execute the following query in the PostreSQL administration interface. And we get a sorted output of information on the database tables.
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)
As you can see, in my case, the djang_session table has grown very much over the 6 years of the site's existence on the Django engine.
Thanks to DDOS visitors, the mechanism for creating session keys for all anonymous users, and the fact that by default PostgreSQL does not reduce the size of the database file even when deleting records.
And the size of the database can be seen like this
SELECT pg_size_pretty( pg_database_size('databasename') ); pg_size_pretty ---------------- 14 GB (1 row)
Here is such an unpleasant size came out - 14 GB.
Deleting expired sessions
When a site is DDOSed or simply flooded with users, a huge number of sessions are created that are usually not deleted in Django, and the table index grows additionally.
Therefore, the first thing to do is to remove obsolete sessions. Django has the clearsessions command for this.
Therefore, in the console we activate the python environment of your project, go to the folder with your project and execute the following command.
python manage.py clearsessions
This will delete all old sessions. You can also schedule this command to run via cron.
For example, using the django-session-cleanup battery, it requires the use of celery .
Run the garbage collector
After you have completed the removal of old sessions, you need to free up the space occupied by the database.
This is necessary because the database's priority is performance over disk space savings. Thus, the database file grows due to the growth of the index, and the data has not been there for a long time. And also, by default, the garbage collector does not start by itself, for this you need to configure it to start on a schedule, for example, using a daemon.
But personally, I've done it manually so far. The garbage collector in PostgreSQL is started with the vacuum command.
vacuum FULL ANALYZE django_session;
After performing this operation, I check the size of the database again and see
SELECT pg_size_pretty( pg_database_size('databasename') ); pg_size_pretty ---------------- 494 MB (1 row)
Now the database size is only 494 MB, which is good news.
It will be necessary over time to configure the garbage collector to run at least once a week, but more on that in the next article.
А если хранить сессии в SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' ?
Интересно стало насколько безопасно хранить сессии в печеньках... стоит оно того или нет?)
Думаю, что скорее всего это будет менее безопасно, но на практике я не проверял.