索引
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 Migrate 能夠建立帶有此引數的約束和索引。這意味著你可以在 Prisma schema 的 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 型別將索引資料以更快搜索和插入的格式儲存,並且會佔用更少的磁碟空間。但是,只有 = 和 <> 比較可以使用索引,因此其他比較運算子(如 < 和 >)在使用 Hash 時會比使用預設 BTree 型別慢得多。
例如,以下模型在 value 欄位上添加了一個 type 為 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 資料。這對於加快查詢一個物件是否是另一個物件的一部分非常有用。它通常用於全文搜尋。
索引欄位可以定義運算子類,該類定義了索引處理的運算子。
Prisma ORM 尚不支援使用函式(例如 to_tsvector)來確定索引值的索引。以這種方式定義的索引在使用 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 Schema Language 中定義:在 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 schema 啟用該功能時,這些索引配置更改可能是重大更改。啟用使用它們所需的預覽功能後,執行 prisma db pull 內省現有資料庫以更新你的 Prisma schema,然後再使用 Prisma Migrate。
在以下情況下可能會發生重大更改
- 現有排序約束和索引: 早期版本的 Prisma ORM 將假定如果未明確指定順序,則所需的排序順序是升序。這意味著如果你有使用降序排序的現有約束或索引,並且在資料模型中未先指定此項就遷移資料庫,則這是一項重大更改。
- 現有長度約束和索引: 在早期版本的 Prisma ORM 中,MySQL 中受長度約束的索引和約束無法在 Prisma schema 中表示。因此
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 schema 中,並且在 Prisma schema 中新增的新全文索引在使用 Prisma Migrate 時會在資料庫中建立。這還可以防止以前無法正常工作的一些資料庫 schema 中的驗證錯誤。
目前,我們尚未在 Prisma Client for MongoDB 中啟用全文搜尋命令;可以在 MongoDB issue 中檢視進展。
啟用 fullTextIndex 預覽功能
要啟用 fullTextIndex 預覽功能,請將 fullTextIndex 功能標誌新增到 schema.prisma 檔案的 generator 塊中
generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextIndex"]
}
示例
以下示例演示瞭如何向 Post 模型的 title 和 content 欄位新增 @@fulltext 索引
model Post {
id Int @id
title String @db.VarChar(255)
content String @db.Text
@@fulltext([title, content])
}
在 MongoDB 上,你可以使用 @@fulltext 索引屬性(透過 fullTextIndex 預覽功能)和 sort 引數,以升序或降序向全文索引新增欄位。以下示例向 Post 模型的 title 和 content 欄位添加了一個 @@fulltext 索引,並以降序對 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 schema 啟用該功能時,這可能是重大更改。啟用使用它們所需的預覽功能後,執行 prisma db pull 內省現有資料庫以更新你的 Prisma schema,然後再使用 Prisma Migrate。
早期版本的 Prisma ORM 使用 @@index 屬性而不是 @@fulltext 屬性轉換全文索引。啟用 fullTextIndex 預覽功能後,執行 prisma db pull 將這些索引轉換為 @@fulltext,然後再使用 Prisma Migrate 進行遷移。如果你不這樣做,現有索引將被刪除,取而代之的是建立普通索引。