インデックス
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ドキュメントを参照してください。
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)
}
Prisma Migrateは、データモデルで指定されていれば、length
引数を使用して制約とインデックスを作成できます。これにより、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
を一緒に使用する
以下の例は、Post
モデルのインデックスと制約を設定するために、sort
とlength
引数を使用する方法を示しています。
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でインデックスタイプを設定するために利用できます。利用可能なインデックスアクセスメソッドは、デフォルトのBTree
インデックスアクセスメソッドの他に、Hash
、Gist
、Gin
、SpGist
、Brin
です。type
引数はバージョン4.0.0以降で一般提供されています。Hash
インデックスアクセスメソッドはバージョン3.6.0以降でextendedIndexes
プレビュー機能の一部として利用可能であり、Gist
、Gin
、SpGist
、Brin
インデックスアクセスメソッドはバージョン3.14.0以降でプレビュー版として利用可能です。
Hash
Hash
タイプは、インデックスデータを検索および挿入がはるかに高速で、ディスクスペースを少なく使用する形式で保存します。ただし、=
および<>
の比較のみがインデックスを使用できるため、<
や>
のような他の比較演算子は、デフォルトのBTree
タイプを使用する場合よりもHash
を使用した場合の方がはるかに遅くなります。
例として、以下のモデルは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 Schema Languageで定義できません。ops
引数はCockroachDBでは不要または許可されていません。
汎用検索ツリー (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);
value > '10.0.0.2'
のようなIPアドレスを比較するクエリは、このインデックスを使用します。
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 |
テーブルは、最大1つのクラスター化インデックスを持つことができます。
以前のバージョンからのアップグレード
これらのインデックス設定の変更は、特定の既存のデータベースの既存のPrismaスキーマの機能を有効にする際に、**破壊的な変更**となる可能性があります。必要なプレビュー機能を有効にした後、prisma db pull
を実行して既存のデータベースをイントロスペクトし、Prisma Migrateを再度使用する前にPrismaスキーマを更新してください。
以下の状況で破壊的な変更が発生する可能性があります
- 既存のソート制約とインデックス: 以前のバージョンの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スキーマに追加された新しい全文インデックスは、Prisma Migrateを使用する際にデータベースに作成されます。これにより、以前機能しなかった一部のデータベーススキーマでの検証エラーも防止されます。
現在、MongoDB用Prisma Clientでは全文検索コマンドは有効にしていません。進捗状況はMongoDBのissueで追跡できます。
fullTextIndex
プレビュー機能の有効化
fullTextIndex
プレビュー機能を有効にするには、schema.prisma
ファイルのgenerator
ブロックにfullTextIndex
機能フラグを追加します
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スキーマの機能を有効にする際に、**破壊的な変更**となる可能性があります。必要なプレビュー機能を有効にした後、prisma db pull
を実行して既存のデータベースをイントロスペクトし、Prisma Migrateを再度使用する前にPrismaスキーマを更新してください。
以前のバージョンのPrisma ORMは、全文インデックスを@@fulltext
属性ではなく@@index
属性を使用して変換していました。fullTextIndex
プレビュー機能を有効にした後、prisma db pull
を実行してこれらのインデックスを@@fulltext
に変換してから、Prisma Migrateで再度マイグレーションしてください。これを行わないと、既存のインデックスは削除され、その代わりに通常のインデックスが作成されます。