What are the downsides of default ordering by PK in Django?

Django models now support default ordering, via Meta.ordering. What are the downsides to putting ordering = ["pk"] on my base model?

In particular, I'm curious about the performance impact. The Django docs have a vague warning that this can hurt performance:

Ordering is not free; each field to order by is an operation the database must perform. If a model has a default ordering (Meta.ordering) and you don’t need it, remove it on a QuerySet by calling order_by() with no parameters.

But is ordering by the primary key actually expensive if I'm using Postgres as my database?

I would say that setting ordering = ['pk'] in your base model might come with some cost in PostgreSQL if we are dealing with a project with large queries.

One of such is that PostgreSQL may have to sort queries that don't require ordering such as ChildModel.objects.all(), ChildModel.objects.count(), etc. which can lead to reduced speed in large queries. As noted in the docs, ordering is not free and comes with a cost.

Thus setting ordering = ['pk'] on a base model, will force all models that inherit from it to inherit this ordering except you override Meta.ordering on the models you want to set a default ordering. This can lead to performance bottlenecks and slower queries. So speed might be an issue with larger projects.

As an aside, if the base model uses UUIDs as pk or other non-sequential primary keys, Meta.ordering = ['pk'] might give non-deterministic ordering.

So I would say if the project is small, this might not be significant but in large projects, it could be expensive.

Ordering is always an extra step, although databases are quite good at it, especially if the field you are ordering on, is in an index, and the primary key is always in an index. So we are good.

However, the queries will take a bit longer, and for queries where you are paginating the result, it can have more impact: if you ask "give me the first 50 rows", then the database can make a query plan, and just throw results at you until it has 50 of those rows. If you ask the first 50 rows based on a certain ordering, then it does not per se needs to determine the full result set, but then it has to evaluate certain operations in a particular order, which of course can slow down processing.

That being said, I don't think it is much of a big deal here: if you paginate results, and you don't order them, it can result in inconsistent ordering over the different requests, so that is not a good idea anyway.

Вернуться на верх