Benchmark¶
Contents
Introduction¶
This benchmark does not intend to be exhaustive nor fair to SQL. It shows how django-cachalot behaves on an unoptimised application. On an application using perfectly optimised SQL queries only, django-cachalot may not be useful. Unfortunately, most Django apps (including Django itself) use unoptimised queries. Of course, they often lack useful indexes (even though it only requires 20 characters per index…). But what you may not know is that the ORM currently generates totally unoptimised queries [1].
Conditions¶
In this benchmark, a small database is generated, and each test is executed 20 times under the following conditions:
CPU | Intel(R) Core(TM) i7-2670QM CPU @ 2.20GHz |
RAM | 20536732 kB |
Disk | INTEL SSDSC2CW06 |
Linux distribution | Ubuntu 16.04 xenial |
Python | 3.6.1 |
Django | 1.11.2 |
cachalot | 1.5.0 |
sqlite | 3.11.0 |
PostgreSQL | 9.6.3 |
MySQL | 5.7.18 |
Redis | 3.0.6 |
memcached | 1.4.25 |
psycopg2 | 2.7.1 |
mysqlclient | 1.3.10 |
Note that MySQL’s query cache is active during the benchmark.
Database results¶
- mysql is 1.1× slower then 4.5× faster
- postgresql is 1.1× slower then 10.3× faster
- sqlite is 1.1× slower then 5.8× faster
Cache results¶
- filebased is 1.1× slower then 6.6× faster
- locmem is 1.0× slower then 7.4× faster
- memcached is 1.1× slower then 6.7× faster
- pylibmc is 1.1× slower then 6.8× faster
- redis is 1.1× slower then 6.7× faster
Cache detailed results¶
Redis¶
[1] | The ORM fetches way too much data if you don’t restrict it using
.only and .defer . You can divide the execution time
of most queries by 2-3 by specifying what you want to fetch.
But specifying which data we want for each query is very long
and unmaintainable. An automation using field usage statistics
is possible and would drastically improve performance.
Other performance issues occur with slicing.
You can often optimise a sliced query using a subquery, like
YourModel.objects.filter(pk__in=YourModel.objects.filter(…)[10000:10050]).select_related(…)
instead of YourModel.objects.filter(…).select_related(…)[10000:10050] .
I’ll maybe work on these issues one day. |