未索引列上的查询
优化提供建议,帮助您识别和解决由缺少数据库索引引起的性能问题。
以下针对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:完整表扫描会增加磁盘输入/输出操作,可能减慢其他数据库活动。
警告
虽然由于数据集较小,这些问题可能不会在开发中出现,但它们在生产环境中可能会成为严重的问题,因为生产环境中的数据集通常要大得多。
更多关于数据库索引的信息
索引的工作原理
索引创建了一个数据结构,该结构存储索引列的值以及指向表中相应行的指针。当您使用索引列查询数据库时,数据库可以使用此索引快速找到相关行,而不是扫描整个表。
索引的权衡
- 空间与时间:索引需要额外的存储空间来保存索引数据,但它显着加快了数据检索速度。
- 更新开销:每次向表中添加、更新或删除数据时,都需要一定的开销来保持索引的最新状态,这可能会减慢写入操作的速度。
何时使用索引
何时不使用索引
- 小型表:对于行数很少的表,维护索引的开销可能不值得性能提升。
- 写入密集型表:索引会减慢写入操作(
create
、update
、delete
)的速度,因为索引也需要更新。避免在写入操作频繁的模型上过度使用索引。 - 很少访问的表:如果很少访问某个表,索引的好处可能不值得开销。
- 包含大型数据的列:索引包含大型数据的列会导致更高的存储需求,并且可能无法提供显着的性能改进。
- 很少过滤的列:如果经常访问某个表,但很少按特定列进行过滤,则在该列上创建索引可能没有好处。
警告
即使您为列建立索引,数据库也可能不会始终使用它。许多数据库管理系统,如 PostgreSQL 和 MySQL,都有一个查询优化器,它会评估多个执行计划并选择它估计最有效的计划。在某些情况下,这可能涉及忽略现有索引,而选择它认为对特定查询执行效果更好的其他执行计划。