---
title: "模型索引参考"
version: 6.1
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/6.1/ref/models/indexes/
canonical: https://djangodocs.dev/zh-hans/6.1/ref/models/indexes/
---
# 模型索引参考

索引类便于创建数据库索引。它们可以使用 [`Meta.indexes`](/zh-hans/6.1/ref/models/options/#django.db.models.Options.indexes) 选项来添加。本文档解释了 [`Index`](#django.db.models.Index) 的 API 引用，其中包括 [index options](#index-options) 。

> **引用内置索引**
>
> 索引是在 `django.db.models.indexes` 中定义的，但为了方便，它们被导入到 [`django.db.models`](/zh-hans/6.1/topics/db/models/#module-django.db.models) 中。标准的惯例是使用 `from django.db import models` 并将索引称为 `models. <IndexClass>`。

## `Index` 选项

#### `class Index(*expressions, fields=(), name=None, db_tablespace=None, opclasses=(), condition=None, include=None)`

在数据库中创建一个索引（B 树）。

### `expressions`

#### `Index.expressions`

位置参数 `*expressions` 允许在表达式和数据库函数上创建函数索引。

例子：

```
Index(Lower("title").desc(), "pub_date", name="lower_title_date_idx")
```

在 `title` 字段的小写字母上按降序创建索引，在 `pub_date` 字段上按默认升序创建索引。

另一个例子：

```
Index(F("height") * F("weight"), Round("weight"), name="calc_idx")
```

在字段 `height` 和 `weight` 相乘的结果上创建一个索引，`weight` 四舍五入为最接近的整数。

[`Index.name`](#django.db.models.Index.name) 在使用 `*expressions` 时是必需的。

> **Oracle 的限制**
>
> Oracle 要求索引中引用的函数被标记为 `DETERMINISTIC`。Django 并不验证这一点，但 Oracle 会出错。这意味着诸如 `Random()` 这样的函数不被接受。

> **PostgreSQL 的限制**
>
> PostgreSQL 要求在索引中引用的函数和运算符被标记为 `IMMUTABLE`。Django 并不验证这一点，但 PostgreSQL 会出错。这意味着诸如 `Concat()` 这样的函数不被接受。

> **MariaDB**
>
> Functional indexes are unsupported and ignored with MariaDB.

### `fields`

#### `Index.fields`

需要索引字段的名称列表或元组。

默认情况下，索引是以每列的升序创建的。要为列定义一个降序索引，请在字段名前添加一个连字符。

例如，`Index(fields=['headline', '-pub_date'])` 将创建具有 `(headline, pub_date DESC)` 的 SQL。

### `name`

#### `Index.name`

索引的名称。如果没有提供 `name`，Django 会自动生成一个名称。为了兼容不同的数据库，索引名不能超过 30 个字符，并且不应该以数字（0-9）或下划线（\_）开头。

> **抽象基类中的部分索引**
>
> 你必须始终为索引指定一个唯一的名称。因此，通常不能在抽象基类上指定部分索引，因为 [`Meta.indexes`](/zh-hans/6.1/ref/models/options/#django.db.models.Options.indexes) 选项是由子类继承的，每次的属性值（包括 `name` ）都完全相同。为了解决名称碰撞的问题，名称的一部分可以包含 `'%(app_label)s'` 和 `'%(class)s'`，它们分别被具体模型的小写应用标签和类名所代替。例如 `Index(field=['title'], name='%(app_label)s_%(class)s_title_index')`。

### `db_tablespace`

#### `Index.db_tablespace`

该索引要使用的 [数据库表空间](/zh-hans/6.1/topics/db/tablespaces/) 名称。对于单字段索引，如果没有提供 `db_tablespace`，则在字段的 `db_tablespace` 中创建索引。

如果没有指定 [`Field.db_tablespace`](/zh-hans/6.1/ref/models/fields/#django.db.models.Field.db_tablespace) （或者如果索引使用了多个字段），则在模型的 `class Meta` 里面的 [`db_tablespace`](/zh-hans/6.1/ref/models/options/#django.db.models.Options.db_tablespace) 选项中指定的表空间创建索引。如果这两个表空间都没有设置，则在与表相同的表空间中创建索引。

> **See also**
>
> 关于 PostgreSQL 特有的索引列表，请参见 [`django.contrib.postgres.indexes`](/zh-hans/6.1/ref/contrib/postgres/indexes/#module-django.contrib.postgres.indexes)。

### `opclasses`

#### `Index.opclasses`

要为这个索引使用的 [PostgreSQL 运算符类](https://www.postgresql.org/docs/current/indexes-opclass.html) 名称。如果你需要一个自定义的操作类，你必须为索引中的每个字段提供一个操作类。

例如，`GinIndex(name='json_index', fields=['jsonfield'], opclasses=['jsonb_path_ops'])` 使用 `jsonb_path_ops` 在 `jsonfield` 上创建一个 gin 索引。

`opclasses` 对于 PostgreSQL 以外的数据库来说是被忽略的。

[`Index.name`](#django.db.models.Index.name) 在使用 `opclasses` 时需要。

### `condition`

#### `Index.condition`

如果表非常大，而且你的查询主要针对行的子集，那么将索引限制在该子集上可能会很有用。将条件指定为 [`Q`](/zh-hans/6.1/ref/models/querysets/#django.db.models.Q)。例如，`condition=Q(pages__gt=400)` 对超过 400 页的记录进行索引。

[`Index.name`](#django.db.models.Index.name) 在使用 `condition` 时需要。

> **PostgreSQL 的限制**
>
> PostgreSQL 要求条件中引用的函数必须标记为 IMMUTABLE。Django 不会验证这一点，但 PostgreSQL 会报错。这意味着诸如 [日期函数](/zh-hans/6.1/ref/models/database-functions/#date-functions) 和 `Concat` 这样的函数不被接受。如果你把日期存储在 [`DateTimeField`](/zh-hans/6.1/ref/models/fields/#django.db.models.DateTimeField) 中，与 [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) 对象进行比较时，可能需要提供 `tzinfo` 参数，否则比较的结果可能是一个可变的函数，因为 Django 对 lookups 进行了转换。

> **SQLite 的限制**
>
> SQLite 对如何构建部分索引 [施加了限制](https://www.sqlite.org/partialindex.html) 。

> **Oracle**
>
> Oracle 不支持部分索引。相反，部分索引可以通过使用函数索引和 [`Case`](/zh-hans/6.1/ref/models/conditional-expressions/#django.db.models.expressions.Case) 表达式来进行模拟。

> **MySQL 和 MariaDB**
>
> 在 MySQL 和 MariaDB 中，`condition` 参数被忽略，因为它们都不支持条件索引。

### `include`

#### `Index.include`

一个包含在覆盖索引中作为非键列的字段名称的列表或元组。这允许仅索引扫描，用于只选择包含的字段（ [`include`](#django.db.models.Index.include) ）和只通过索引字段过滤的查询（ [`fields`](#django.db.models.Index.fields)）。

例子：

```
Index(name="covering_index", fields=["headline"], include=["pub_date"])
```

将允许对  `headline` 进行过滤，同时选择 `pub_date`，而只从索引中获取数据。

使用 `include` 将产生一个比使用多列索引更小的索引，但缺点是不能使用非键列进行排序或过滤。

`include` 对于 PostgreSQL 以外的数据库来说是被忽略的。

[`Index.name`](#django.db.models.Index.name) 在使用 `include` 时是必需的。

关于 [covering indexes](https://www.postgresql.org/docs/current/indexes-index-only-scans.html) 的更多细节，请参阅 PostgreSQL 文档。

> **PostgreSQL-specific indexes**
>
> In addition to B-Tree indexes (via [`Index`](#django.db.models.Index)), PostgreSQL also
> supports [`GistIndex`](/zh-hans/6.1/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.GistIndex) and
> [`SpGistIndex`](/zh-hans/6.1/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.SpGistIndex) indexes.
