Indexes

Django ORM creates indices for primary and foreign keys out of the box. However, if you perform a lot of queries on the rest of the columns (the columns that are used in a filter() method) it makes sense to add indexes to them. This can be accomplished by adding db_index=True or unique=True argument to a model field.

N+1 problem

If you do a lot of cross-table queries (loading data from multiple tables) you might end up with N+1 problem. N+1 problem is when ORM produces an additional query for each associated row you’re fetching. This can be solved by using select_related() and prefetch_related() methods when making queries.

Extra columns

When a table has a lot of columns, loading every column on each query has a potential to ruin your performance. Leave out the columns you don’t need and fetch the ones that you’re going to use: using values() or only() ORM methods will solve this problem.