模型索引参考¶
索引类简化了数据库索引的创建。它们可以使用 Meta.indexes
选项添加。本文档解释了 Index
的 API 参考,其中包括 索引选项。
引用内置索引
索引定义在 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")
在 height
和 weight
字段相乘的结果以及 weight
四舍五入到最近的整数的结果上创建索引。
使用 *expressions
时需要 Index.name
。
Oracle 的限制
Oracle 要求索引中引用的函数标记为 DETERMINISTIC
。Django 不会验证这一点,但 Oracle 会报错。这意味着诸如 Random()
之类的函数不被接受。
PostgreSQL 的限制
PostgreSQL 要求索引中引用的函数和运算符标记为 IMMUTABLE
。Django 不会验证这一点,但 PostgreSQL 会报错。这意味着诸如 Concat()
之类的函数不被接受。
MySQL 和 MariaDB
MySQL < 8.0.13 和 MariaDB 忽略函数索引,因为两者都不支持它们。
fields
¶
- Index.fields¶
要创建索引的字段名称列表或元组。
默认情况下,索引是为每一列创建升序的。要定义对列进行降序排序的索引,请在字段名称前添加一个连字符。
例如 Index(fields=['headline', '-pub_date'])
将创建带有 (headline, pub_date DESC)
的 SQL。
MariaDB
MariaDB < 10.8 不支持索引排序。在这种情况下,降序索引将作为普通索引创建。
name
¶
- Index.name¶
索引的名称。如果未提供 name
,Django 将自动生成一个名称。为了与不同的数据库兼容,索引名称不能超过 30 个字符,并且不能以数字 (0-9) 或下划线 (_) 开头。
抽象基类中的部分索引
您必须始终为索引指定唯一的名称。因此,您通常无法在抽象基类上指定部分索引,因为 Meta.indexes
选项由子类继承,并且每次属性(包括 name
)的值完全相同。为了解决名称冲突,名称的一部分可以包含 '%(app_label)s'
和 '%(class)s'
,它们分别被具体模型的小写应用标签和类名替换。例如 Index(fields=['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
选项中指定的表空间中创建。如果这两个表空间都没有设置,则索引将在与表相同的表空间中创建。
另请参阅
有关 PostgreSQL 特定索引的列表,请参阅 django.contrib.postgres.indexes
。
opclasses
¶
- Index.opclasses¶
要用于此索引的 PostgreSQL 运算符类 的名称。如果您需要自定义运算符类,则必须为索引中的每个字段提供一个。
例如,GinIndex(name='json_index', fields=['jsonfield'], opclasses=['jsonb_path_ops'])
使用 jsonb_path_ops
在 jsonfield
上创建 gin 索引。
除了 PostgreSQL 之外的数据库会忽略 opclasses
。
使用 opclasses
时需要 Index.name
。
condition
¶
- Index.condition¶
如果表非常大,并且您的查询主要针对子集行,则限制索引到该子集可能很有用。将条件指定为 Q
。例如,condition=Q(pages__gt=400)
为页面数超过 400 的记录建立索引。
使用 condition
时需要 Index.name
。
PostgreSQL 的限制
PostgreSQL 要求条件中引用的函数标记为 IMMUTABLE。Django 不会验证这一点,但 PostgreSQL 会报错。这意味着诸如 日期函数 和 Concat
之类的函数不被接受。如果您将日期存储在 DateTimeField
中,与 datetime
对象的比较可能需要提供 tzinfo
参数,因为否则由于 Django 对 查找 进行的转换,比较可能会导致可变函数。
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 以外的数据库会被忽略。
使用 include
时需要 Index.name
。
有关 覆盖索引 的更多详细信息,请参阅 PostgreSQL 文档。
PostgreSQL 的限制
PostgreSQL 支持覆盖 B 树和 GiST 索引
。PostgreSQL 14+ 还支持覆盖 SP-GiST 索引
。