模型索引参考

索引类便于创建数据库索引。它们可以使用 Meta.indexes 选项来添加。本文档解释了 Index 的 API 引用,其中包括 index options

引用内置索引

索引是在 django.db.models.indexes 中定义的,但为了方便,它们被导入到 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)[source]

在数据库中创建一个索引(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")

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

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 选项是由子类继承的,每次的属性值(包括 name )都完全相同。为了解决名称碰撞的问题,名称的一部分可以包含 '%(app_label)s''%(class)s',它们分别被具体模型的小写应用标签和类名所代替。例如 Index(field=['title'], name='%(app_label)s_%(class)s_title_index')

db_tablespace

Index.db_tablespace

该索引要使用的 数据库表空间 名称。对于单字段索引,如果没有提供 db_tablespace,则在字段的 db_tablespace 中创建索引。

如果没有指定 Field.db_tablespace (或者如果索引使用了多个字段),则在模型的 class Meta 里面的 db_tablespace 选项中指定的表空间创建索引。如果这两个表空间都没有设置,则在与表相同的表空间中创建索引。

See also

关于 PostgreSQL 特有的索引列表,请参见 django.contrib.postgres.indexes

opclasses

Index.opclasses

要为这个索引使用的 PostgreSQL 运算符类 名称。如果你需要一个自定义的操作类,你必须为索引中的每个字段提供一个操作类。

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

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

Index.name 在使用 opclasses 时需要。

condition

Index.condition

如果表非常大,而且你的查询主要针对行的子集,那么将索引限制在该子集上可能会很有用。将条件指定为 Q。例如,condition=Q(pages__gt=400) 对超过 400 页的记录进行索引。

Index.name 在使用 condition 时需要。

PostgreSQL 的限制

PostgreSQL 要求条件中引用的函数必须标记为 IMMUTABLE。Django 不会验证这一点,但 PostgreSQL 会报错。这意味着诸如 日期函数Concat 这样的函数不被接受。如果你把日期存储在 DateTimeField 中,与 datetime 对象进行比较时,可能需要提供 tzinfo 参数,否则比较的结果可能是一个可变的函数,因为 Django 对 lookups 进行了转换。

SQLite 的限制

SQLite 对如何构建部分索引 施加了限制

Oracle

Oracle 不支持部分索引。相反,部分索引可以通过使用函数索引和 Case 表达式来进行模拟。

MySQL 和 MariaDB

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

include

Index.include

一个包含在覆盖索引中作为非键列的字段名称的列表或元组。这允许仅索引扫描,用于只选择包含的字段( include )和只通过索引字段过滤的查询( fields)。

例子:

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

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

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

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

Index.name 在使用 include 时是必需的。

关于 covering indexes 的更多细节,请参阅 PostgreSQL 文档。

PostgreSQL-specific indexes

In addition to B-Tree indexes (via Index), PostgreSQL also supports GistIndex and SpGistIndex indexes.