Save your Django models using update_fields for better performance

The Django ORM is designed to turn the rows of your database tables into objects that can then conform to object oriented principles. This makes it very easy to create, update and delete entries from your database.

However, there are certain advantages to using raw queries instead of an ORM. For instance when you update a row in your table, you might want to update only a subset of the columns in that row and not all of the columns.

Saving a Django model object updates all your columns every single time you call a save() method. To prevent this from happening you must be explicit.

What save() does internally

Consider a Django model called Record which has the following fields:



If you would like to update the name of a record you might do something like this



If you turn on logs in the underlying database that you are using which in my case is Postgres, the query that actually runs is this:



This may not seem like a big deal, but what if your model consisted of 20 fields and you run a save() operation on it very frequently? 

At a certain scale the database query that updates all of your columns every time you call save() can start causing you some unnecessary overhead. 

Why is the overhead unnecessary? Because it can be prevented with a simple tweak.

Use update_fields in save()

If you would like to explicitly mention only those columns that you want to be updated, you can do so using the update_fields parameter while calling the save() method.



The underlying query now becomes



You can also choose to update multiple columns by passing more field names in the update_fields list. 

This is clearly a more efficient way to run your queries and will save you some database overhead.

Efficiency aside, this also helps avoid concurrency issues when two threads are trying to save the same object but update different fields.

TL;DR

If you use the save() method with the intention of updating some specific columns in your database row, explicitly mention those fields by using the update_fields parameter and calling the save() method like this:

obj.save(update_fields=['field_1', 'field_2']) as opposed to just obj.save()

This will save you some database overhead by making the underlying query more efficient.