Skip to content

Model Indexes

Database indexes improve query performance by allowing the database to locate data without scanning every row in a table. In Django, you define indexes within the Meta class of your model using the indexes list.

Basic Usage

To create an index, add an instance of models.Index to the indexes list in your model's Meta class. You must specify which fields to index.

python
from django.db import models

class Customer(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    city = models.CharField(max_length=100)

    class Meta:
        indexes = [
            models.Index(fields=['last_name', 'first_name']),
            models.Index(fields=['last_name'], name='lastname_idx'),
        ]

Common Index Options

The models.Index class accepts several arguments to customize how the index is built. The table below outlines the most frequently used options.

OptionDescription
fieldsA list of field names to include in the index. Use a hyphen (Ex: '-pub_date') to specify descending order.
nameThe name of the index in the database. If you do not provide one, Django automatically generates it.
conditionA Q object used to create a "partial index." This restricts the index to a subset of rows (Ex: only active users).
includeA list of extra fields to store in the index as non-key columns. This allows queries to retrieve data directly from the index (Covering Index).
db_tablespaceThe name of the database tablespace to use for this index.

For a complete list of Index options, refer to the Django Model Index Reference.

Functional Indexes

You can create indexes on the result of expressions or database functions rather than simple field values. This is useful for optimizing queries that filter by transformed data, such as case-insensitive searches.

To use this, pass the expression as a positional argument before any keyword arguments.

python
from django.db.models.functions import Lower

class Meta:
    indexes = [
        # Index the lowercased value of the 'city' field
        models.Index(Lower('city'), name='city_lower_idx'),
    ]

Partial Indexes

If you have a large table but your queries mostly target a specific subset of rows, you can use a partial index. This saves space and improves performance by only indexing rows that match a specific condition.

python
from django.db.models import Q

class Meta:
    indexes = [
        # Only index customers who reside in 'New York'
        models.Index(
            fields=['first_name'], 
            condition=Q(city='New York'), 
            name='ny_customers_idx'
        ),
    ]