在 Prisma Postgres 中缓存查询
Prisma Postgres 支持内置查询缓存,以减少数据库负载并提高查询性能。您可以使用所有读取查询中可用的 cacheStrategy 选项配置缓存行为。
此功能由通过 Prisma Accelerate 启用的内部缓存层提供支持,但除非您使用自己的数据库,否则无需直接与 Accelerate 交互。
在 Prisma Postgres 中设置缓存
要在您的 Prisma Postgres 项目中启用查询缓存,您需要配置 Accelerate 缓存并设置客户端扩展。请遵循以下步骤:
1. 在平台控制台中启用缓存
- 前往并导航到您的项目仪表板
- 在“连接到您的数据库”部分,点击 连接
- 切换 启用 Accelerate 缓存 以激活缓存层
- 复制生成的连接字符串
您的连接字符串将如下所示:
DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=ey...."
用这个新的 Accelerate 启用 URL 替换您的 .env 文件中的连接字符串。
2. 安装 Accelerate 扩展
在您的项目中安装所需的客户端扩展
npm install @prisma/extension-accelerate
3. 使用缓存配置 Prisma Client
更新您的 Prisma Client 设置以使用 Accelerate 扩展
- 标准运行时
- 边缘运行时
import { PrismaClient } from '../generated/prisma/client'
import { withAccelerate } from '@prisma/extension-accelerate'
const prisma = new PrismaClient({
accelerateUrl: process.env.DATABASE_URL,
}).$extends(withAccelerate())
import { PrismaClient } from '@prisma/client/edge'
import { withAccelerate } from '@prisma/extension-accelerate'
const prisma = new PrismaClient({
accelerateUrl: process.env.DATABASE_URL,
}).$extends(withAccelerate())
4. 开始缓存您的查询
配置完成后,您可以使用 cacheStrategy 选项将缓存添加到任何读取查询中
await prisma.user.findMany({
cacheStrategy: {
ttl: 60, // Cache for 60 seconds
},
})
您的缓存设置现已完成!继续阅读以了解不同的缓存策略以及如何针对您的用例进行优化。
缓存策略
对于 Prisma Client 中的所有读取查询,您可以定义配置缓存行为的 cacheStrategy 参数。缓存策略允许您定义缓存的两个主要特征:
- 存活时间 (TTL): 缓存响应被视为“新鲜”的持续时间(以秒为单位)。
- 过期时重新验证 (SWR): 在后台刷新缓存时,过期缓存响应被视为可接受的持续时间(以秒为单位)
存活时间 (TTL)
存活时间 (TTL) 决定缓存数据被视为新鲜的时间。通过以秒为单位指定 ttl,您可以控制缓存中数据保持有效的时间。当执行读取查询时,如果缓存响应在 ttl 限制内,Prisma Client 将从缓存中检索数据,而无需查询数据库。如果缓存数据不可用或已过期,Prisma Client 将查询数据库并将结果存储在缓存中以供将来请求使用。
在 cacheStrategy 中使用 ttl 并以秒为单位指定查询的 TTL
await prisma.user.findMany({
cacheStrategy: {
ttl: 60,
},
});
在指定 60 秒的 TTL 后,大多数请求在 TTL 持续时间内都会导致缓存命中

TTL 对于减少不需要频繁更新的数据的数据库负载和延迟非常有用。
使 TTL 失效并保持缓存查询结果最新
如果您的应用程序需要实时或准实时数据,缓存失效可确保用户看到最新数据,即使使用较长的 ttl(存活时间)也是如此。通过使缓存失效,您可以绕过延长的缓存期,以便在需要时显示实时数据。
例如,如果仪表板显示客户信息,并且客户的联系方式发生变化,TTL(存活时间)设置可确保缓存在一组持续时间后自动过期。这允许系统在下次访问时仅刷新更新的数据,确保支持人员始终看到最新信息,而无需手动刷新缓存。
但是,在 TTL 过期之前需要立即更新的情况下,缓存失效允许系统主动清除缓存中的特定数据。这会强制立即刷新更新的信息,因此支持人员始终拥有最新详细信息,而无需等待 TTL 触发。
要使缓存的查询结果失效,您可以添加标签,然后使用 $accelerate.invalidate API。
按需缓存失效适用于我们的付费计划。有关更多详细信息,请参阅我们的 定价。
要使以下查询失效,您需要在 $accelerate.invalidate API 中提供缓存标签
await prisma.user.findMany({
cacheStrategy: {
ttl: 60,
tags: ["findMany_users"],
},
});
// This is how you would invalidate the cached query above.
await prisma.$accelerate.invalidate({
tags: ["findMany_users"],
});
过期时重新验证 (SWR)
过期时重新验证 (SWR) 允许您控制 Prisma Postgres 在后台获取新数据时可以提供过期缓存数据的时间。当执行读取查询时,Prisma Postgres 会根据 swr 持续时间检查缓存响应的年龄。如果缓存数据在 swr 限制内,Prisma Postgres 会提供过期数据,同时通过从数据库获取最新数据来刷新缓存。
在 cacheStrategy 中使用 swr 并以秒为单位指定查询的 SWR
await prisma.user.findMany({
cacheStrategy: {
swr: 60,
},
});
当指定 SWR 为 60 秒时,缓存会提供过期数据,直到缓存在每次请求后在后台自行刷新

使 SWR 失效并保持缓存查询结果最新
如果您的应用程序需要实时或准实时数据,缓存失效可确保用户看到最新数据,即使使用较长的 swr(过期时重新验证)也是如此。通过使缓存失效,您可以绕过延长的缓存期,以便在需要时显示实时数据。
例如,考虑一个显示仓库中产品库存水平的仪表板。通过 SWR(过期时重新验证)设置,仪表板可以立即显示上次已知的库存数据,即使它略微过期,同时在后台获取新数据。这可确保工作人员可以继续使用最新信息而无需等待,并且库存水平会在重新验证完成后立即更新。
但是,在需要立即更新库存数据的情况下(例如,如果产品库存不足且计数需要实时准确性),缓存失效允许系统主动清除缓存中的特定数据。这会强制立即刷新最新库存数据,因此工作人员始终拥有最新信息,而无需等待 SWR 完成重新验证。
要使缓存的查询结果失效,您可以添加标签,然后使用 $accelerate.invalidate API。
按需缓存失效适用于我们的付费计划。有关更多详细信息,请参阅我们的 定价。
要使以下查询失效,您需要在 $accelerate.invalidate API 中提供缓存标签
await prisma.user.findMany({
cacheStrategy: {
swr: 60,
tags: ["findMany_users"],
},
});
// This is how you would invalidate the cached query above.
await prisma.$accelerate.invalidate({
tags: ["findMany_users"],
});
选择缓存策略
缓存可帮助您提高查询响应时间并减少数据库负载。但是,这也意味着您可能会向客户端提供过期数据。是否接受提供过期数据以及在何种程度上取决于您的用例。 ttl 和 swr 是您可以用来调整缓存行为的参数。
使用 TTL 的缓存策略
当过期缓存数据可接受时,使用 TTL 减少数据库负载。
用例:电子商务应用程序中的产品目录
考虑一个产品目录不经常更改的电子商务应用程序。通过设置一个,比如说,1 小时的 ttl,Prisma Client 可以在该小时内为后续用户请求提供缓存的产品数据,而无需访问数据库。这显著减少了数据库负载并提高了产品列表页面的响应时间。
何时失效: 如果目录有关键更新,例如重大价格变动或产品可用性调整,应立即使缓存失效,以防止客户看到过时信息。
使用 SWR 的缓存策略
使用 SWR 快速响应请求,并提供最少的过期数据。虽然它不能减少数据库负载,但可以显著提高响应时间。
用例:社交媒体平台中的用户资料
想象一个社交媒体平台,用户资料被频繁访问。通过利用持续时间为 5 分钟的 swr,Prisma Postgres 可以快速提供缓存的用户资料信息,从而减少资料页面的延迟。同时,在后台,它会在每次请求后刷新缓存,确保对资料所做的任何更新最终都会反映在后续请求中。
何时失效: 如果用户对其资料进行重大更新,例如更改其资料图片或简介,应立即使缓存失效,以确保关注者看到最新更新,而无需等待 SWR 刷新。
使用 TTL + SWR 的缓存策略
为了实现非常快的响应时间和减少数据库负载,请同时使用 TTL 和 SWR。您可以使用此策略微调应用程序对过期数据的容忍度。
在 cacheStrategy 中使用 ttl 和 swr 并以秒为单位指定查询的 TTL 和 SWR
await prisma.user.findMany({
cacheStrategy: {
ttl: 30,
swr: 60,
},
});
当指定 TTL 为 30 秒和 SWR 为 60 秒时,缓存会在最初的 30 秒内提供新鲜数据。随后,它会提供过期数据,直到缓存在每次请求后在后台自行刷新

用例:新闻文章
考虑一个新闻应用程序,文章被频繁访问但不需要实时更新。通过设置 2 小时的 ttl 和 5 分钟的 swr 持续时间,Prisma Client 可以快速提供缓存的文章,减少读者的延迟。只要文章在 ttl 内,用户就可以获得快速响应。ttl 过期后,Prisma Client 会继续提供过期的文章长达额外 5 分钟,并在响应新查询时使用数据库中的最新新闻重新验证缓存。这有助于在性能和新鲜度之间保持平衡。
何时失效: 如果发布了关键更新或突发新闻文章,应立即使缓存失效,以确保读者及时看到最新信息。此方法对于某些新闻项目可能需要覆盖正常缓存周期以保持时效性的应用程序特别有用。
按需缓存失效
如果您的应用程序需要实时或准实时数据,缓存失效可确保用户看到最新数据,即使使用较长的 ttl(存活时间)或 swr(过期时重新验证)缓存策略也是如此。通过使缓存失效,您可以绕过延长的缓存期,以便在需要时显示实时数据。
您可以使用 $accelerate.invalidate API 使缓存失效
要以编程方式使缓存查询失效,需要付费计划。有关更多详细信息,请参阅我们的 定价。
await prisma.user.findMany({
where: {
email: {
contains: "alice@prisma.io",
},
},
cacheStrategy: {
swr: 60,
ttl: 60,
tags: ["emails_with_alice"],
},
});
您需要在 $accelerate.invalidate API 中提供缓存标签
try {
await prisma.$accelerate.invalidate({
tags: ["emails_with_alice"],
});
} catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
// The .code property can be accessed in a type-safe manner
if (e.code === "P6003") {
console.log(
"The cache invalidation rate limit has been reached. Please try again later."
);
}
}
throw e;
}
探索演示应用程序,了解 Prisma Postgres 中缓存的查询结果如何按需失效,并在清晰的时间轴中显示。
默认缓存策略
Prisma Postgres 默认情况下不缓存,以避免意外问题。虽然缓存可以提高性能,但使用不当可能会导致错误。
例如,如果在关键路径上执行查询而未指定缓存策略,结果可能会不正确,且没有明确的解释。此问题通常在无意中启用隐式缓存时发生。
为避免此类问题,您必须明确选择启用缓存。这可确保您知道默认情况下未启用缓存,从而防止潜在错误。
当未指定缓存策略或缓存未命中时,缓存层将所有查询通过靠近数据库区域的连接池实例路由到数据库。