模型索引参考 — Django 文档
型号索引参考
索引类简化了创建数据库索引的过程。 可以使用 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)
- 在数据库中创建索引(B 树)。
expressions
- Index.expressions
3.2 版中的新功能。
位置参数 *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。 MySQL 不支持索引排序。 在这种情况下,会创建一个降序索引作为普通索引。
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 选项中指定的表空间中创建索引. 如果这两个表空间都没有设置,则在与表相同的表空间中创建索引。
opclasses
- Index.opclasses
用于此索引的 PostgreSQL 运算符类 的名称。 如果您需要自定义运算符类,则必须为索引中的每个字段提供一个。
例如,GinIndex(name='json_index', fields=['jsonfield'], opclasses=['jsonb_path_ops'])
使用 jsonb_path_ops
在 jsonfield
上创建一个 gin 索引。
opclasses
对于 PostgreSQL 以外的数据库将被忽略。
使用 opclasses
时需要 Index.name。
condition
- Index.condition
如果表非常大并且您的查询主要针对行的子集,则将索引限制为该子集可能很有用。 将条件指定为 Q。 例如,condition=Q(pages__gt=400)
索引超过 400 页的记录。
使用 condition
时需要 Index.name。
对 PostgreSQL 的限制
PostgreSQL 要求将条件中引用的函数标记为 IMMUTABLE。 Django 不会验证这一点,但 PostgreSQL 会出错。 这意味着不接受诸如 Date 函数 和 Concat 之类的函数。 如果您将日期存储在 DateTimeField 中,与 datetime
对象的比较可能需要提供 tzinfo
参数,否则比较可能会由于转换 Django 而导致可变函数用于 查找 。
MySQL 和 MariaDB
MySQL 和 MariaDB 会忽略 condition
参数,因为它们都不支持条件索引。
include
- Index.include
3.2 版中的新功能。
要作为非键列包含在覆盖索引中的字段名称的列表或元组。 这允许仅索引扫描用于仅选择包含字段 (include) 和仅按索引字段过滤 (fields) 的查询。
例如:
Index(name='covering_index', fields=['headline'], include=['pub_date'])
将允许过滤 headline
,同时选择 pub_date
,同时仅从索引中获取数据。
使用 include
将产生比使用多列索引更小的索引,但缺点是非键列不能用于排序或过滤。
include
对于 PostgreSQL 以外的数据库被忽略。
使用 include
时需要 Index.name。
有关 覆盖索引 的更多详细信息,请参阅 PostgreSQL 文档。