5👍
Differences in annotations, properties, and other methods
There are some cases where annotations are definitely better and easier than properties. These are usually calculations that are easy to make in the database and where the logic is easy to read.
Django @property
, on the other hand, is a very easy and Pythonic way to write calculation logic into your models. Some think they are neat things, others think properties should be burned and hidden away because they mix program logic into data objects, which increases complexity. I think that especially the @cached_property
decorator is rather neat.
Properties and annotations are not, however, the only ways to query and calculate things in the Django ORM.
In many complex cases properties or Model, Manager, or QuerySet methods, especially with custom QuerySets and Managers have the most flexibility when it comes to customizing your queries.
Most of the time it does not matter which method you use speed-wise, and should use the cleanest or most compact option that is the simplest to write and easiest to read. Try to keep it simple and stupid and you will have the least amount of complex code to maintain.
Exploring, benchmarking, and optimizing
In some cases when you have performance problems and end up analyzing your SQL queries you might be forced to use annotations and custom queries to optimize the complexities of queries you are making. This can be especially true when you are making complex lookups in the database and have to resort to calculating things in either properties or create custom SQL queries.
Calculating stuff in properties can be horrible for complexity if you have large querysets, because you have to run those calculations in Python where objects are large and iteration is slow. On the other hand, calculating stuff via custom SQL queries can be a nightmare to maintain, especially if the SQL you are maintaining is not, well, written by you.
In the end it comes down to the speed requirements and costs of calculation. If calculating in plain Python doesn’t slow your service down or cost you money, you shouldn’t probably optimize. If you are paying for a fleet of servers then, of course, reasonable optimization might bring you savings that you can use elsewhere. Using 10 hours on optimizing some snippet might not really pay itself back, so be very careful here.
In optimization cases you have to weigh different up and downsides and try different solutions if you are not a prophet and instinctively know what the problem is. If the problem was obvious, it would have been probably optimized away earlier, right?
When experimenting with different options the Django Debug Toolbar, SQL EXPLAIN and ANALYZE and Python profiling are your friends.
Remember that many query problems are also database related problems and you might be hurting your performance with poor database design or maintenance. Remember to run VACUUM periodically and try to normalize your database design.
Toolwise Django Debug Toolbar is especially useful because it can be help with both profiling and SQL analyzing. Many IDEs such as PyCharm also offer profiling on even a running server. This is pretty useful if you want to have your development setup and integrate different tools into it.