インデックスが付けられていない列でのクエリ
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: フルテーブルスキャンはディスク入出力操作を増加させ、他のデータベースアクティビティを遅くする可能性があります。
これらの問題は、データセットが小さいため開発環境では現れないかもしれませんが、データセットが通常ははるかに大きい本番環境では、深刻な問題となる可能性があります。
データベースインデックスについてさらに
インデックスの仕組み
インデックスは、インデックスが付けられた列の値と、テーブル内の対応する行へのポインタを格納するデータ構造を作成します。インデックスが付けられた列を使用してデータベースをクエリすると、データベースはこのインデックスを使用して、テーブル全体をスキャンする代わりに、関連する行を迅速に特定できます。
インデックス付けのトレードオフ
- スペースと時間: インデックス付けにはインデックスデータを保存するための追加のストレージスペースが必要ですが、データ取得を大幅に高速化します。
- 更新オーバーヘッド: データがテーブルに追加、更新、または削除されるたびに、インデックスを最新の状態に保つためのオーバーヘッドが発生し、書き込み操作が遅くなる可能性があります。
インデックスを使用する場合
- 大規模なデータセット: インデックスは、多数の行を持つテーブルに特に有益です。
- フィルタリングまたはソートを伴う頻繁なクエリ: 頻繁にフィルタリングまたはソートに使用される列にインデックスを使用します。
- 関連データの検索: 関連レコードの取得を高速化するために、外部キー列にインデックスを使用します。たとえば、
include
を使用する場合などです。
インデックスを使用しない場合
- 小さなテーブル: 行数が非常に少ないテーブルでは、インデックスを維持するオーバーヘッドがパフォーマンス向上に見合わない場合があります。
- 書き込み負荷の高いテーブル: インデックスも更新する必要があるため、インデックスは書き込み操作(
create
、update
、delete
)を遅くする可能性があります。頻繁な書き込み操作を伴うモデルでの過剰なインデックス付けは避けてください。 - アクセス頻度の低いテーブル: テーブルへのアクセスがまれな場合、インデックス付けの利点はオーバーヘッドを正当化しない可能性があります。
- 大規模なデータを持つ列: 大規模なデータを持つ列にインデックスを付けると、より高いストレージ要件につながり、大幅なパフォーマンス改善が得られない場合があります。
- めったにフィルタリングされない列: テーブルが頻繁にアクセスされるものの、特定の列でフィルタリングされることがめったにない場合、その列にインデックスを作成することは有益ではない可能性があります。
列にインデックスを付けても、データベースが常にそれを使用するとは限りません。PostgreSQLやMySQLなどの多くのデータベース管理システムには、複数の実行計画を評価し、最も効率的であると推定されるものを選択するクエリ最適化機能があります。場合によっては、特定のクエリに対してより良いパフォーマンスを発揮すると判断された異なる実行計画を優先して、既存のインデックスを無視することがあります。