跳到主要内容

未索引列上的查询

优化功能提供建议,帮助您识别和解决因缺少数据库索引而导致的性能问题。

以下针对 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 时。

何时不使用索引

  • 小型表: 对于行数很少的表,维护索引的开销可能不值得性能提升。
  • 写入密集型表: 索引可能会减慢写入操作(createupdatedelete),因为索引也需要更新。避免在具有频繁写入操作的模型上过度索引。
  • 不经常访问的表: 如果很少访问表,则索引的好处可能无法证明开销是合理的。
  • 包含大型数据的列: 索引包含大型数据的列可能会导致更高的存储需求,并且可能无法提供显着的性能改进。
  • 很少过滤的列: 如果经常访问表,但很少按特定列进行过滤,则在该列上创建索引可能没有益处。
警告

即使您索引了一列,数据库也可能不总是使用它。许多数据库管理系统(如 PostgreSQL 和 MySQL)都有一个查询优化器,它可以评估多个执行计划并选择它估计最有效的计划。在某些情况下,这可能涉及忽略现有索引,而选择它确定对于该特定查询将表现更好的不同执行计划。