mirror of
https://github.com/Hopiu/django-cachalot.git
synced 2026-05-14 07:33:10 +00:00
This PR upgrades cachalot to version 2.2.0 allowing for anyone to install cachalot at any Django package above 1.11. All tests currently function now. * Added mysql as a service to fix Travis CI * Removed tox dependency * Removed upper limit on Django and support 2.2-3.0 CI Test * Cachalot will only say "officially supports" while removing upper limit to not hinder anyone's progress. * Added Python 3.8 and Django 2.2 and 3.0 to CI tests - Max is 200 and we'll get there quickly if we add another Python version. Utilizes #127 - Keep dependencies for six and django.utils.six * Correctly run Travis test by updating tox.ini * Originally using tox syntax but changed testenv to travis so that travis env and travis dependencies and stuff are used * Tox tests should start running command * testenv without dependencies broke travis. New spot in Tox * testenv without dependencies broke travis * I can't figure out where testenv is supposed to be * Good thing there's squash * Added missing six in test * Also added six package to Tox for Django 3.0 coverage. * The missing six package caused several problems in several tests due to using an incorrect DB * Resolves #138 * Need to add the panels here in order to satisfy tests * Adds CachalotPanel to Python 2 backwards compatibility * Forgot super class took those like save() * Added databases to certain test cases * APITestCase, DebugToolbarTestCase, SignalsTestCase required a database set * Fixes errors like these: https://travis-ci.org/noripyt/django-cachalot/jobs/648691385#L4892 * Dropped OFFICIAL support for Python 3.4 + MySQL * MySQL and its client on 3.4 is f--king up a lot of the testing and I can't bear with it. We can revisit it later, but, honestly, who uses Python 3.4... and if an organization is, then they will either have no problem with Postgres and SQLite or know that MySQL doesn't work. * Drop Py3.4 from running. Fixed databases * Now goes with setting's databases rather than hardcoded since some tests don't have other databases. * Fix ReadTestCase Django 2.2+ changed self.queryset at line 1000 with self.query=queryset.query * Django Dependency Removed from utils.py * Last commit used Django version. This one used try except * Fixed assertNumQuery; added allow_failures for 3.4 * Primary: More information in test_utils.py with method is_django_21_below_and_is_sqlite * The problem with the entire build lie in the self.is_sqlite for the tests. SQLite will make 2 queries when creating or destroying or updating instead of 1. * In summary, if SQLite is the DB and Django * Changed build matrix to allow failures for 3.4 instead of taking it out completely so that we can get it to work soon. * Remove -> From function return * I love backwards compatibility * SQLite2 in multi_db.py returned incorrect bool * Django 2.1 and SQLite checker doesn't work for some tests * Some tests DO HAVE the BEGIN query that is returned... Not sure why. If the next test show completely different WriteTestCase problems, then we need to find alternative. * Removed check from atomic * Adjust Django and is_sqlite errors * CI testing the Tox errors: https://travis-ci.org/noripyt/django-cachalot?utm_medium=notification&utm_source=github_status * Adjust Django and is_sqlite errors (590 CI) * CI testing the Tox errors: https://travis-ci.org/noripyt/django-cachalot?utm_medium=notification&utm_source=github_status * Adjustment 2 * Make include matrix and Adjust Django and is_sqlite errors (594 CI) * CI testing the Tox errors: https://travis-ci.org/noripyt/django-cachalot?utm_medium=notification&utm_source=github_status * Adjustment 3 * Adjust Django and is_sqlite errors (596 CI) * CI testing the Tox errors: https://travis-ci.org/noripyt/django-cachalot?utm_medium=notification&utm_source=github_status * Adjustment 4 * Added my intro to ReadTheDocs * Adjust Django and is_sqlite errors (598 CI) * CI testing the Tox errors: https://travis-ci.org/noripyt/django-cachalot?utm_medium=notification&utm_source=github_status * Adjustment 5 * Drop Python 3.4 from tests since PyLibMC not cooperating at that level. * Bump package version up 1 minor for Django 2.2 and 3.0
145 lines
7.5 KiB
ReStructuredText
145 lines
7.5 KiB
ReStructuredText
.. _Introduction:
|
||
|
||
Introduction
|
||
------------
|
||
|
||
Should you use it?
|
||
..................
|
||
|
||
Django-cachalot is the perfect speedup tool for most Django projects.
|
||
It will speedup a website of 100 000 visits per month without any problem.
|
||
In fact, **the more visitors you have, the faster the website becomes**.
|
||
That’s because every possible SQL query on the project ends up being cached.
|
||
|
||
Django-cachalot is especially efficient in the Django administration website
|
||
since it’s unfortunately badly optimised (use foreign keys in ``list_editable``
|
||
if you need to be convinced).
|
||
|
||
However, it’s not suited for projects where there is **a high number
|
||
of modifications per second** on each table, like a social network with
|
||
more than a 50 messages per second. Django-cachalot may still give a small
|
||
speedup in such cases, but it may also slow things a bit
|
||
(in the worst case scenario, a 20% slowdown,
|
||
according to :ref:`the benchmark <Benchmark>`).
|
||
If you have a website like that, optimising your SQL database and queries
|
||
is the number one thing you have to do.
|
||
|
||
There is also an obvious case where you don’t need django-cachalot:
|
||
when the project is already fast enough (all pages load in less than 300 ms).
|
||
Like any other dependency, django-cachalot is a potential source of problems
|
||
(even though it’s currently bug free).
|
||
Don’t use dependencies you can avoid, a “future you” may thank you for that.
|
||
|
||
Features
|
||
........
|
||
|
||
- **Saves in cache the results of any SQL query** generated by the Django ORM
|
||
that reads data. These saved results are then returned instead
|
||
of executing the same SQL query, which is faster.
|
||
- The first time a query is executed is about 10% slower, then the following
|
||
times are way faster (7× faster being the average).
|
||
- Automatically invalidates saved results,
|
||
so that **you never get stale results**.
|
||
- **Invalidates per table, not per object**: if you change an object,
|
||
all the queries done on other objects of the same model are also invalidated.
|
||
This is unfortunately technically impossible to make a reliable
|
||
per-object cache. Don’t be fooled by packages pretending having
|
||
that per-object feature, they are unreliable and dangerous for your data.
|
||
- **Handles everything in the ORM**. You can use the most advanced features
|
||
from the ORM without a single issue, django-cachalot is extremely robust.
|
||
- An easy control thanks to :ref:`settings` and :ref:`a simple API <API>`.
|
||
But that’s only required if you have a complex infrastructure. Most people
|
||
will never use settings or the API.
|
||
- A few bonus features like
|
||
:ref:`a signal triggered at each database change <Signal>`
|
||
(including bulk changes) and
|
||
:ref:`a template tag for a better template fragment caching <Template utils>`.
|
||
|
||
Comparison with similar tools
|
||
.............................
|
||
|
||
This comparison was done in December 2015. It compares django-cachalot
|
||
to the other popular automatic ORM caches at the moment:
|
||
`django-cache-machine <https://github.com/django-cache-machine/django-cache-machine>`_
|
||
& `django-cacheops <https://github.com/Suor/django-cacheops>`_.
|
||
|
||
Features
|
||
~~~~~~~~
|
||
|
||
===================================================== ========= ============= ==========
|
||
Feature cachalot cache-machine cacheops
|
||
===================================================== ========= ============= ==========
|
||
Easy to install ✔ ✘ quite
|
||
Cache agnostic ✔ ✔ ✘
|
||
Type of invalidation per table per object per query
|
||
CPU performance excellent excellent excellent
|
||
Memory performance excellent good excellent
|
||
Reliable ✔ ✘ ✘
|
||
Useful for > 50 modifications per minute ✘ ✔ ✔
|
||
Handles transactions ✔ ✘ ✘
|
||
Handles Django admin save ✔ ✘ ✘
|
||
Handles multi-table inheritance ✔ ✔ ✘
|
||
Handles ``QuerySet.count`` ✔ ✘ ✔
|
||
Handles ``QuerySet.aggregate``/``annotate`` ✔ ✔ ✘
|
||
Handles ``QuerySet.update`` ✔ ✘ ✘
|
||
Handles ``QuerySet.select_related`` ✔ ✔ ✘
|
||
Handles ``QuerySet.extra`` ✔ ✘ ✘
|
||
Handles ``QuerySet.values``/``values_list`` ✔ ✘ ✔
|
||
Handles ``QuerySet.dates``/``datetimes`` ✔ ✘ ✔
|
||
Handles subqueries ✔ ✔ ✘
|
||
Handles querysets generating a SQL ``HAVING`` keyword ✔ ✔ ✘
|
||
Handles ``cursor.execute`` ✔ ✘ ✘
|
||
Handles the Django command ``flush`` ✔ ✘ ✘
|
||
===================================================== ========= ============= ==========
|
||
|
||
Explanations
|
||
''''''''''''
|
||
|
||
“Handles [a feature]” means that the package correctly invalidates SQL queries
|
||
using that feature. So if a package doesn’t handle a feature, you may get
|
||
stale query results when using this feature.
|
||
It does not mean that it caches a query with this feature, although
|
||
django-cachalot caches all queries except random queries
|
||
or those ran through ``cursor.execute``.
|
||
|
||
This comparison was done by running the test suite of cachalot against
|
||
cache-machine & cacheops. This test suite is indeed relevant for other
|
||
packages (such as cache-machine & cacheops) since most of it is written in
|
||
a cachalot-independent way.
|
||
|
||
Similarly, the performance comparison was done using our benchmark,
|
||
coupled with a memory measure.
|
||
|
||
To me, cache-machine & cacheops are not reliable because of these reasons:
|
||
|
||
- Neither cache-machine or cacheops handle transactions, which is critical.
|
||
**Transactions are used a lot in Django internals**: at least
|
||
in any Django admin save, many-to-many relations modification,
|
||
bulk creation or update, migrations, session save.
|
||
If an error occurs during one of these operations, good luck finding
|
||
if stale data is returned. The best you can do in this case is manually
|
||
clearing the cache.
|
||
- If you use a query that’s not handled, you may get stale data. It ends up
|
||
ruining your database since it lets you save modifications to stale data,
|
||
therefore overwriting the latest version that’s in the database.
|
||
And you always end up using queries that are not handled since there is no
|
||
list of unhandled queries in the documentation of each module.
|
||
- In the case of cache-machine, another issue is that it relies
|
||
on “flush lists”, which can’t work reliably when implemented in a cache
|
||
like this (see `cache-machine#107 <https://github.com/django-cache-machine/django-cache-machine/issues/107>`_).
|
||
|
||
|
||
Number of lines of code
|
||
~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
Django-cachalot tries to be as minimalist as possible, while handling most
|
||
use cases. Being minimalist is essential to create maintainable projects,
|
||
and having a large test suite is essential to get an excellent quality.
|
||
The statistics below speak for themselves…
|
||
|
||
============ ======== ============= ========
|
||
Project part cachalot cache-machine cacheops
|
||
============ ======== ============= ========
|
||
Application 743 843 1662
|
||
Tests 3023 659 1491
|
||
============ ======== ============= ========
|