インデックスが設定されていない列に対するクエリ
Optimize は、データベースインデックスの欠落によって引き起こされるパフォーマンスの問題を特定し、解決するのに役立つ推奨事項を提供します。
次の User
モデルを対象とするクエリは、where
プロパティを使用して、インデックスが設定されていない列でフィルタリングします。
await prisma.user.findFirst({
where: {
name: "Marc"
}
})
await prisma.user.findFirst({
where: {
name: "Jon"
}
})
await prisma.user.count({
where: {
name: "Nikolas"
}
})
何が問題か?
インデックスを使用すると、データベースはより迅速にデータを取得できます。これは、書籍の索引がすべてのページを読まずに情報を探すのに役立つ方法と似ています。
Prisma を where
プロパティとともに使用する場合、関連する列にインデックスが定義されていないと、データベースは一致するものを検索するためにテーブル内のすべての行(「フルテーブルスキャン」)をスキャンする必要がある場合があります。これは、いくつかの理由から望ましくありません。
ユーザーエクスペリエンス
データセットが大きい場合、データベースが一致する行を見つけるためにテーブル全体をスキャンする必要がある場合、ユーザーは待機時間が長くなることを経験します。
リソース使用率
- CPU使用率の高さ:大きなテーブルをスキャンすると、CPU使用率が大幅に増加し、システム全体のパフォーマンスが低下する可能性があります。
- メモリ消費量:フルテーブルスキャン中にデータを処理および保存するためにより多くのメモリが必要です。
- ディスクI/O:フルテーブルスキャンは、ディスクの入出力操作を増加させ、他のデータベースアクティビティを遅くする可能性があります。
これらの問題は、データセットが小さいため開発環境では表面化しないかもしれませんが、データセットが通常はるかに大きい本番環境では重大な問題になる可能性があります。
データベースインデックスの詳細
インデックスの仕組み
インデックスは、インデックス付き列の値と、テーブル内の対応する行へのポインタを格納するデータ構造を作成します。インデックス付き列を使用してデータベースにクエリを実行すると、データベースはこのインデックスを使用して、テーブル全体をスキャンする代わりに、関連する行をすばやく見つけることができます。
インデックス作成のトレードオフ
- スペース vs. 時間:インデックス作成には、インデックスデータを保存するための追加のストレージスペースが必要ですが、データ取得が大幅に高速化されます。
- 更新オーバーヘッド:テーブルでデータの追加、更新、または削除が行われるたびに、インデックスを最新の状態に保つためのオーバーヘッドが発生し、書き込み操作が遅くなる可能性があります。
インデックスを使用する場合
- 大規模なデータセット:インデックスは、行数の多いテーブルに特に役立ちます。
- フィルタリングまたはソートを伴う頻繁なクエリ:フィルタリングまたはソートによく使用される列にインデックスを使用します。
- 関連データの検索:
include
を使用する場合など、外部キー列にインデックスを使用して、関連レコードの取得を高速化します。
インデックスを使用しない場合
- 小さなテーブル:行数が非常に少ないテーブルの場合、インデックスを維持するオーバーヘッドは、パフォーマンスの向上に見合わない場合があります。
- 書き込み負荷の高いテーブル:インデックスは、インデックスも更新する必要があるため、書き込み操作(
create
、update
、delete
)を遅くする可能性があります。頻繁な書き込み操作があるモデルでは、過剰なインデックス作成を避けてください。 - アクセス頻度の低いテーブル:テーブルへのアクセスがまれな場合、インデックス作成のメリットはオーバーヘッドに見合わない場合があります。
- 大きなデータを持つ列:大きなデータを持つ列にインデックスを作成すると、ストレージ要件が高くなり、パフォーマンスが大幅に向上しない可能性があります。
- めったにフィルタリングされない列:テーブルによくアクセスするが、特定の列でフィルタリングすることがめったにない場合、その列にインデックスを作成しても有益ではない場合があります。
列にインデックスを設定しても、データベースが常にそれを使用するとは限りません。PostgreSQL や MySQL などの多くのデータベース管理システムには、複数の実行プランを評価し、最も効率的であると推定されるプランを選択するクエリオプティマイザがあります。場合によっては、特定のクエリに対してより適切に実行されると判断した別の実行プランを優先して、既存のインデックスを無視することがあります。