索引
Prisma ORM 允许配置数据库索引、唯一约束和主键约束。此功能在 4.0.0
及更高版本中已投入通用使用。你可以在 3.5.0
及更高版本中使用 extendedIndexes
预览功能启用此功能。
3.6.0
版本还通过新的 @@fulltext
属性引入了对 MySQL 和 MongoDB 中全文索引的内省和迁移支持,该属性可通过 fullTextIndex
预览功能使用。
如果你正在从 4.0.0 之前的版本升级,如果你有一个已经使用这些功能的数据库,这些对索引配置和全文索引的更改可能是 **重大更改**。有关如何升级的更多信息,请参阅 从先前版本升级。
索引配置
你可以使用以下属性参数配置索引、唯一约束和主键约束
-
length
参数 允许你为String
和Bytes
类型上要索引的值子部分指定最大长度- 适用于
@id
、@@id
、@unique
、@@unique
和@@index
属性 - 仅限 MySQL
- 适用于
-
sort
参数 允许你指定约束或索引的条目在数据库中存储的顺序- 适用于所有数据库中的
@unique
、@@unique
和@@index
属性,以及 SQL Server 中的@id
和@@id
属性
- 适用于所有数据库中的
-
type
参数 允许你支持除 PostgreSQL 默认的BTree
访问方法之外的索引访问方法- 适用于
@@index
属性 - 仅限 PostgreSQL
- 支持的索引访问方法:
Hash
、Gist
、Gin
、SpGist
和Brin
- 适用于
-
clustered
参数 允许你配置约束或索引是聚集还是非聚集- 适用于
@id
、@@id
、@unique
、@@unique
和@@index
属性 - 仅限 SQL Server
- 适用于
有关每个功能首次引入的版本的详细信息,请参阅链接部分。
使用 length
配置索引长度(MySQL)
length
参数是 MySQL 特定的,允许你为 String
和 Byte
类型的列定义索引和约束。对于这些类型,MySQL 要求你指定要索引的值子部分的最大长度,在完整值超过 MySQL 索引大小限制的情况下。有关更多详细信息,请参阅 MySQL 文档。
length
参数适用于 @id
、@@id
、@unique
、@@unique
和 @@index
属性。它在 4.0.0 及更高版本中普遍可用,并且在 3.5.0 及更高版本中作为 extendedIndexes
预览功能的一部分可用。
例如,以下数据模型声明了一个最大长度为 3000 个字符的 id
字段
model Id {
id String @id @db.VarChar(3000)
}
这在 MySQL 中无效,因为它超过了 MySQL 的索引存储限制,因此 Prisma ORM 会拒绝该数据模型。生成的 SQL 会被数据库拒绝。
CREATE TABLE `Id` (
`id` VARCHAR(3000) PRIMARY KEY
)
length
参数允许你指定只有 id
值的子部分代表主键。在下面的示例中,使用前 100 个字符
model Id {
id String @id(length: 100) @db.VarChar(3000)
}
如果在你的数据模型中指定了 length
参数,Prisma 迁移能够创建具有该参数的约束和索引。这意味着你可以在 Prisma 架构类型 Byte
和 String
的值上创建索引和约束。如果你没有指定该参数,索引将像以前一样被视为覆盖完整的值。
内省将在你的现有数据库中存在的地方获取这些限制。这使 Prisma ORM 能够支持以前被抑制的索引和约束,从而更好地支持使用此功能的 MySQL 数据库。
length
参数也可以用于复合主键,使用 @@id
属性,如下例所示
model CompoundId {
id_1 String @db.VarChar(3000)
id_2 String @db.VarChar(3000)
@@id([id_1(length: 100), id_2(length: 10)])
}
类似的语法可用于 @@unique
和 @@index
属性。
使用 sort
配置索引排序顺序
sort
参数适用于 Prisma ORM 支持的所有数据库。它允许你指定索引或约束的条目在数据库中存储的顺序。这可能会影响数据库是否能够使用索引来执行特定查询。
sort
参数适用于所有数据库中的 @unique
、@@unique
和 @@index
。此外,SQL Server 还允许它在 @id
和 @@id
上使用。它在 4.0.0 及更高版本中普遍可用,并且在 3.5.0 及更高版本中作为 extendedIndexes
预览功能的一部分可用。
例如,以下表格
CREATE TABLE `Unique` (
`unique` INT,
CONSTRAINT `Unique_unique_key` UNIQUE (`unique` DESC)
)
现在被内省为
model Unique {
unique Int @unique(sort: Desc)
}
sort
参数也可以用于复合索引
model CompoundUnique {
unique_1 Int
unique_2 Int
@@unique([unique_1(sort: Desc), unique_2])
}
示例:将 sort
和 length
结合使用
以下示例演示了如何使用 sort
和 length
参数为 Post
模型配置索引和约束
model Post {
title String @db.VarChar(300)
abstract String @db.VarChar(3000)
slug String @unique(sort: Desc, length: 42) @db.VarChar(3000)
author String
created_at DateTime
@@id([title(length: 100, sort: Desc), abstract(length: 10)])
@@index([author, created_at(sort: Desc)])
}
使用 type
配置索引的访问类型(PostgreSQL)
type
参数可用于使用 @@index
属性配置 PostgreSQL 中的索引类型。可用的索引访问方法是 Hash
、Gist
、Gin
、SpGist
和 Brin
,以及默认的 BTree
索引访问方法。type
参数在 4.0.0 及更高版本中普遍可用。Hash
索引访问方法在 3.6.0 及更高版本中作为 extendedIndexes
预览功能的一部分可用,Gist
、Gin
、SpGist
和 Brin
索引访问方法在 3.14.0 及更高版本中作为预览功能可用。
散列
Hash
类型将以一种更快的搜索和插入格式存储索引数据,并且将使用更少的磁盘空间。但是,只有 =
和 <>
比较可以使用索引,因此其他比较运算符(如 <
和 >
)在使用 Hash
时比使用默认的 BTree
类型时要慢得多。
例如,以下模型为 value
字段添加了一个类型为 Hash
的索引
model Example {
id Int @id
value Int
@@index([value], type: Hash)
}
这转换为以下 SQL 命令
CREATE TABLE "Example" (
id INT PRIMARY KEY,
value INT NOT NULL
);
CREATE INDEX "Example_value_idx" ON "Example" USING HASH (value);
通用倒排索引 (GIN)
GIN 索引存储复合值,例如数组或 JsonB
数据。这对于加速查询一个对象是否为另一个对象的一部分非常有用。它通常用于全文搜索。
已索引字段可以定义运算符类,该运算符类定义了索引处理的运算符。
使用函数(如 to_tsvector
)来确定已索引值的索引目前不受 Prisma ORM 支持。以这种方式定义的索引在使用 prisma db pull
时将不可见。
例如,以下模型为 value
字段添加了一个 Gin
索引,其中 JsonbPathOps
是允许使用索引的运算符类
model Example {
id Int @id
value Json
// ^ field type matching the operator class
// ^ operator class ^ index type
@@index([value(ops: JsonbPathOps)], type: Gin)
}
这转换为以下 SQL 命令
CREATE TABLE "Example" (
id INT PRIMARY KEY,
value JSONB NOT NULL
);
CREATE INDEX "Example_value_idx" ON "Example" USING GIN (value jsonb_path_ops);
作为 JsonbPathOps
的一部分,@>
运算符由索引处理,从而加快了诸如 value @> '{"foo": 2}'
之类的查询速度。
GIN 支持的运算符类
Prisma ORM 通常支持 PostgreSQL 10 及更高版本提供的运算符类。如果运算符类要求字段类型为 Prisma ORM 尚未支持的类型,则使用带有字符串输入的 `raw` 函数允许您在没有验证的情况下使用这些运算符类。
默认运算符类(用 ✅ 标记)可以从索引定义中省略。
运算符类 | 允许的字段类型(原生类型) | 默认 | 其他 |
---|---|---|---|
ArrayOps | 任何数组 | ✅ | 也适用于 CockroachDB |
JsonbOps | Json (@db.JsonB ) | ✅ | 也适用于 CockroachDB |
JsonbPathOps | Json (@db.JsonB ) | ||
raw("other") |
有关内置运算符类的更多信息,请参阅 官方 PostgreSQL 文档。
CockroachDB
GIN 和 BTree 是 CockroachDB 支持的唯一索引类型。标记为可与 CockroachDB 一起使用的运算符类是该数据库上允许的唯一运算符类,也是 Prisma ORM 支持的运算符类。运算符类不能在 Prisma 模式语言中定义:CockroachDB 上不需要或不允许 `ops` 参数。
广义搜索树 (GiST)
GiST 索引类型用于实现用户定义类型的索引方案。默认情况下,GiST 索引没有太多直接用途,但例如 B-Tree 索引类型是使用 GiST 索引构建的。
例如,以下模型向 `value` 字段添加一个 `Gist` 索引,使用 `InetOps` 作为将使用索引的运算符
model Example {
id Int @id
value String @db.Inet
// ^ native type matching the operator class
// ^ index type
// ^ operator class
@@index([value(ops: InetOps)], type: Gist)
}
这转换为以下 SQL 命令
CREATE TABLE "Example" (
id INT PRIMARY KEY,
value INET NOT NULL
);
CREATE INDEX "Example_value_idx" ON "Example" USING GIST (value inet_ops);
比较 IP 地址的查询,例如 `value > '10.0.0.2'`,将使用索引。
支持的 GiST 运算符类
Prisma ORM 通常支持 PostgreSQL 10 及更高版本提供的运算符类。如果运算符类要求字段类型为 Prisma ORM 尚未支持的类型,则使用带有字符串输入的 `raw` 函数允许您在没有验证的情况下使用这些运算符类。
运算符类 | 允许的字段类型(允许的原生类型) |
---|---|
InetOps | String (@db.Inet ) |
raw("other") |
有关内置运算符类的更多信息,请参阅 官方 PostgreSQL 文档。
空间分区 GiST (SP-GiST)
对于许多不同的非平衡数据结构,SP-GiST 索引是一个不错的选择。如果查询与分区规则匹配,它可以非常快。
与 GiST 一样,SP-GiST 作为用户定义类型的构建块非常重要,允许直接使用数据库实现自定义搜索运算符。
例如,以下模型向 `value` 字段添加一个 `SpGist` 索引,使用 `TextOps` 作为使用索引的运算符
model Example {
id Int @id
value String
// ^ field type matching the operator class
@@index([value], type: SpGist)
// ^ index type
// ^ using the default ops: TextOps
}
这转换为以下 SQL 命令
CREATE TABLE "Example" (
id INT PRIMARY KEY,
value TEXT NOT NULL
);
CREATE INDEX "Example_value_idx" ON "Example" USING SPGIST (value);
诸如 `value LIKE 'something%'` 之类的查询将通过索引加速。
支持的 SP-GiST 运算符类
Prisma ORM 通常支持 PostgreSQL 10 及更高版本提供的运算符类。如果运算符类要求字段类型为 Prisma ORM 尚未支持的类型,则使用带有字符串输入的 `raw` 函数允许您在没有验证的情况下使用这些运算符类。
默认运算符类(用 ✅ 标记)可以从索引定义中省略。
运算符类 | 允许的字段类型(原生类型) | 默认 | 支持的 PostgreSQL 版本 |
---|---|---|---|
InetOps | String (@db.Inet ) | ✅ | 10+ |
TextOps | String (@db.Text , @db.VarChar ) | ✅ | |
raw("other") |
有关内置运算符类的更多信息,请参阅 官方 PostgreSQL 文档。
块范围索引 (BRIN)
如果您有大量在插入后不会更改的数据(例如日期和时间值),BRIN 索引类型很有用。如果您的数据适合索引,它可以将大型数据集存储在最小空间中。
例如,以下模型向 `value` 字段添加一个 `Brin` 索引,使用 `Int4BloomOps` 作为将使用索引的运算符
model Example {
id Int @id
value Int
// ^ field type matching the operator class
// ^ operator class ^ index type
@@index([value(ops: Int4BloomOps)], type: Brin)
}
这转换为以下 SQL 命令
CREATE TABLE "Example" (
id INT PRIMARY KEY,
value INT4 NOT NULL
);
CREATE INDEX "Example_value_idx" ON "Example" USING BRIN (value int4_bloom_ops);
诸如 `value = 2` 之类的查询现在将使用索引,该索引使用的空间仅为 `BTree` 或 `Hash` 索引使用的空间的一小部分。
支持的 BRIN 运算符类
Prisma ORM 通常支持 PostgreSQL 10 及更高版本提供的运算符类,并且某些支持的运算符仅从 PostgreSQL 14 及更高版本开始可用。如果运算符类要求字段类型为 Prisma ORM 尚未支持的类型,则使用带有字符串输入的 `raw` 函数允许您在没有验证的情况下使用这些运算符类。
默认运算符类(用 ✅ 标记)可以从索引定义中省略。
运算符类 | 允许的字段类型(原生类型) | 默认 | 支持的 PostgreSQL 版本 |
---|---|---|---|
BitMinMaxOps | String (@db.Bit ) | ✅ | |
VarBitMinMaxOps | String (@db.VarBit ) | ✅ | |
BpcharBloomOps | String (@db.Char ) | 14+ | |
BpcharMinMaxOps | String (@db.Char ) | ✅ | |
ByteaBloomOps | Bytes (@db.Bytea ) | 14+ | |
ByteaMinMaxOps | Bytes (@db.Bytea ) | ✅ | |
DateBloomOps | DateTime (@db.Date ) | 14+ | |
DateMinMaxOps | DateTime (@db.Date ) | ✅ | |
DateMinMaxMultiOps | DateTime (@db.Date ) | 14+ | |
Float4BloomOps | Float (@db.Real ) | 14+ | |
Float4MinMaxOps | Float (@db.Real ) | ✅ | |
Float4MinMaxMultiOps | Float (@db.Real ) | 14+ | |
Float8BloomOps | Float (@db.DoublePrecision ) | 14+ | |
Float8MinMaxOps | Float (@db.DoublePrecision ) | ✅ | |
Float8MinMaxMultiOps | Float (@db.DoublePrecision ) | 14+ | |
InetInclusionOps | String (@db.Inet ) | ✅ | 14+ |
InetBloomOps | String (@db.Inet ) | 14+ | |
InetMinMaxOps | String (@db.Inet ) | ||
InetMinMaxMultiOps | String (@db.Inet ) | 14+ | |
Int2BloomOps | Int (@db.SmallInt ) | 14+ | |
Int2MinMaxOps | Int (@db.SmallInt ) | ✅ | |
Int2MinMaxMultiOps | Int (@db.SmallInt ) | 14+ | |
Int4BloomOps | Int (@db.Integer ) | 14+ | |
Int4MinMaxOps | Int (@db.Integer ) | ✅ | |
Int4MinMaxMultiOps | Int (@db.Integer ) | 14+ | |
Int8BloomOps | BigInt (@db.BigInt ) | 14+ | |
Int8MinMaxOps | BigInt (@db.BigInt ) | ✅ | |
Int8MinMaxMultiOps | BigInt (@db.BigInt ) | 14+ | |
NumericBloomOps | Decimal (@db.Decimal ) | 14+ | |
NumericMinMaxOps | Decimal (@db.Decimal ) | ✅ | |
NumericMinMaxMultiOps | Decimal (@db.Decimal ) | 14+ | |
OidBloomOps | Int (@db.Oid ) | 14+ | |
OidMinMaxOps | Int (@db.Oid ) | ✅ | |
OidMinMaxMultiOps | Int (@db.Oid ) | 14+ | |
TextBloomOps | String (@db.Text , @db.VarChar ) | 14+ | |
TextMinMaxOps | String (@db.Text , @db.VarChar ) | ✅ | |
TextMinMaxMultiOps | String (@db.Text , @db.VarChar ) | 14+ | |
TimestampBloomOps | DateTime (@db.Timestamp ) | 14+ | |
TimestampMinMaxOps | DateTime (@db.Timestamp ) | ✅ | |
TimestampMinMaxMultiOps | DateTime (@db.Timestamp ) | 14+ | |
TimestampTzBloomOps | DateTime (@db.Timestamptz ) | 14+ | |
TimestampTzMinMaxOps | DateTime (@db.Timestamptz ) | ✅ | |
TimestampTzMinMaxMultiOps | DateTime (@db.Timestamptz ) | 14+ | |
TimeBloomOps | DateTime (@db.Time ) | 14+ | |
TimeMinMaxOps | DateTime (@db.Time ) | ✅ | |
TimeMinMaxMultiOps | DateTime (@db.Time ) | 14+ | |
TimeTzBloomOps | DateTime (@db.Timetz ) | 14+ | |
TimeTzMinMaxOps | DateTime (@db.Timetz ) | ✅ | |
TimeTzMinMaxMultiOps | DateTime (@db.Timetz ) | 14+ | |
UuidBloomOps | String (@db.Uuid ) | 14+ | |
UuidMinMaxOps | String (@db.Uuid ) | ✅ | |
UuidMinMaxMultiOps | String (@db.Uuid ) | 14+ | |
raw("other") |
有关内置运算符类的更多信息,请参阅 官方 PostgreSQL 文档。
使用 `clustered` 配置索引是否聚集或非聚集(SQL Server)
`clustered` 参数可用于在 SQL Server 中配置(非)聚集索引。它可以在 `@id`、`@@id`、`@unique`、`@@unique` 和 `@@index` 属性上使用。它通常在 4.0.0 及更高版本中可用,并且在 3.13.0 及更高版本中作为 `extendedIndexes` 预览功能的一部分可用。
例如,以下模型将 `@id` 配置为非聚集(而不是默认的聚集)
model Example {
id Int @id(clustered: false)
value Int
}
这转换为以下 SQL 命令
CREATE TABLE [Example] (
id INT NOT NULL,
value INT,
CONSTRAINT [Example_pkey] PRIMARY KEY NONCLUSTERED (id)
)
每个属性的 `clustered` 的默认值为:
属性 | 值 |
---|---|
@id | true |
@@id | true |
@unique | false |
@@unique | false |
@@index | false |
一个表最多可以有一个聚集索引。
从先前版本升级
这些索引配置更改在为某些现有数据库的现有 Prisma 模式激活功能时可能成为重大更改。在启用使用它们所需的预览功能后,运行 `prisma db pull` 以内省现有数据库以更新您的 Prisma 模式,然后再使用 Prisma Migrate。
重大更改可能发生在以下情况下:
- 现有的排序约束和索引:早期的 Prisma ORM 版本将假设所需的排序顺序为升序,如果未明确指定排序顺序。这意味着如果您的现有约束或索引使用降序排序顺序,并且在首先在您的数据模型中指定此顺序之前迁移您的数据库,则这是一个重大更改。
- 现有的长度约束和索引:在早期的 Prisma ORM 版本中,在 MySQL 中长度受约束的索引和约束无法在 Prisma 模式中表示。因此,`prisma db pull` 未获取这些索引,您也无法手动指定它们。当您运行 `prisma db push` 或 `prisma migrate dev` 时,如果它们已存在于您的数据库中,它们会被忽略。由于您现在可以指定这些索引,因此迁移命令现在会删除它们(如果它们在您的数据模型中丢失,但存在于数据库中)。
- 除了 `BTree` 之外的现有索引(PostgreSQL):早期的 Prisma ORM 版本仅支持默认的 `BTree` 索引类型。其他支持的索引(`Hash`、`Gist`、`Gin`、`SpGist` 和 `Brin`)需要在迁移数据库之前添加。
- 现有的(非)聚集索引(SQL Server):早期的 Prisma ORM 版本不支持将索引配置为聚集或非聚集。对于不使用默认值的索引,需要在迁移数据库之前添加这些索引。
在上述每个情况下,可以通过在您的数据模型中适当地指定这些属性来防止对您的数据库进行不必要的更改。执行此操作的最简单方法是使用 `prisma db pull` 来检索任何现有的约束或配置。或者,您也可以手动添加这些参数。这应该在您升级后第一次使用 `prisma db push` 或 `prisma migrate dev` 之前完成。
全文索引 (MySQL 和 MongoDB)
`fullTextIndex` 预览功能在 3.6.0 及更高版本中提供对 MySQL 和 MongoDB 中全文索引的内省和迁移的支持。可以使用 `@@fulltext` 属性配置此功能。在使用 `db pull` 内省后,数据库中的现有全文索引将添加到您的 Prisma 模式中,并且在使用 Prisma Migrate 时,在 Prisma 模式中添加的新全文索引将在数据库中创建。这也避免了在某些先前无法工作的数据库模式中发生验证错误。
目前,我们尚未在 Prisma Client for MongoDB 中启用全文搜索命令;进度可以在 MongoDB 问题中跟踪。
启用 fullTextIndex
预览功能
要启用 fullTextIndex
预览功能,请将 fullTextIndex
功能标志添加到 schema.prisma
文件的 generator
块中
generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextIndex"]
}
示例
以下示例演示了如何将 @@fulltext
索引添加到 Post
模型的 title
和 content
字段
model Post {
id Int @id
title String @db.VarChar(255)
content String @db.Text
@@fulltext([title, content])
}
在 MongoDB 上,您可以使用 @@fulltext
索引属性(通过 fullTextIndex
预览功能)以及 sort
参数,将字段添加到全文索引中,并按升序或降序排序。以下示例将 @@fulltext
索引添加到 Post
模型的 title
和 content
字段,并将 title
字段按降序排序
generator js {
provider = "prisma-client-js"
previewFeatures = ["fullTextIndex"]
}
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
model Post {
id String @id @map("_id") @db.ObjectId
title String
content String
@@fulltext([title(sort: Desc), content])
}
从旧版本升级
对于某些现有数据库的现有 Prisma 架构,激活此功能时可能是一个 **重大变更**。在启用使用它们所需的预览功能后,运行 prisma db pull
来内省现有数据库,以便在再次使用 Prisma Migrate 之前更新您的 Prisma 架构。
早期版本的 Prisma ORM 使用 @@index
属性而不是 @@fulltext
属性转换全文索引。在启用 fullTextIndex
预览功能后,运行 prisma db pull
将这些索引转换为 @@fulltext
,然后使用 Prisma Migrate 再次迁移。如果您没有这样做,现有索引将被删除,取而代之的是普通索引。