模型索引参考

索引类简化了数据库索引的创建。它们可以使用 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

位置参数 *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 四舍五入到最接近的整数的结果上创建索引。

当使用 *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'])jsonfield 上创建一个 gin 索引,使用 jsonb_path_ops

opclasses 被忽略,除了 PostgreSQL 之外的其他数据库。

当使用 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 对 查找 的转换,比较可能会导致可变函数。

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 将生成比使用多列索引更小的索引,但缺点是非键列不能用于排序或过滤。

除了 PostgreSQL 之外的数据库会忽略 include

使用 include 时需要 Index.name

有关 覆盖索引 的更多详细信息,请参阅 PostgreSQL 文档。

PostgreSQL 的限制

PostgreSQL 支持覆盖 B-Tree 和 GiST indexes。PostgreSQL 14+ 还支持覆盖 SP-GiST indexes

返回顶部