跳转到内容
搜索文档

查询缓存

最后更新 查看 MarkdownAgent 设置

启用查询缓存时,Hyperdrive 会自动缓存 Worker 发往数据库的可缓存读查询。这可减轻数据库负载,并避免热门查询到数据库的网络往返。查询缓存默认开启。

Hyperdrive 缓存什么?

Hyperdrive 使用数据库协议区分变更查询(写入数据库)与非变更查询(只读)。Hyperdrive 缓存符合条件的只读查询响应,不缓存写入。

除区分 SELECTINSERT 外,Hyperdrive 还会解析数据库 wire 协议以判断查询是变更还是非变更。

例如,填充新闻网站首页的读查询会被缓存:

-- Cacheable: uses a parameterized date value instead of CURRENT_DATE
SELECT * FROM articles WHERE DATE(published_time) = $1
ORDER BY published_time DESC LIMIT 50
-- Cacheable: uses a parameterized date value instead of CURDATE()
SELECT * FROM articles WHERE DATE(published_time) = ?
ORDER BY published_time DESC LIMIT 50

变更查询(包括 INSERTUPSERTCREATE TABLE)以及使用 PostgreSQL 标记为 volatilestable 的函数的查询不会被缓存:

-- Not cached: mutating queries
INSERT INTO users(id, name, email) VALUES(555, 'Matt', 'hello@example.com');

-- Not cached: LASTVAL() is a volatile function
SELECT LASTVAL(), * FROM articles LIMIT 50;

-- Not cached: NOW() is a stable function
SELECT * FROM events WHERE created_at > NOW() - INTERVAL '1 hour';
-- Not cached: mutating queries
INSERT INTO users(id, name, email) VALUES(555, 'Thomas', 'hello@example.com');

-- Not cached: LAST_INSERT_ID() is a volatile function
SELECT LAST_INSERT_ID(), * FROM articles LIMIT 50;

-- Not cached: NOW() returns a non-deterministic value
SELECT * FROM events WHERE created_at > NOW() - INTERVAL 1 HOUR;

常见不可缓存的 PostgreSQL 函数包括:

函数 PostgreSQL 易变性类别 是否缓存
NOW() STABLE
CURRENT_TIMESTAMP STABLE
CURRENT_DATE STABLE
CURRENT_TIME STABLE
LOCALTIME STABLE
LOCALTIMESTAMP STABLE
TIMEOFDAY() VOLATILE
RANDOM() VOLATILE
LASTVAL() VOLATILE
TXID_CURRENT() STABLE

仅 PostgreSQL 标记为 IMMUTABLE(相同输入返回值不变)的函数与 Hyperdrive 缓存兼容。若查询使用 STABLEVOLATILE 函数,将函数调用移到应用代码,并将结果值作为查询参数传入。

默认缓存设置

Hyperdrive 的默认缓存行为:

  • max_age = 60 秒(1 分钟)
  • stale_while_revalidate = 15 秒

max_age 决定查询响应从缓存提供的最长生命周期。很少使用的缓存响应可能在此时间之前被驱逐。

stale_while_revalidate 允许 Hyperdrive 在重新验证缓存期间继续提供过期缓存结果。大多数情况下,重新验证会很快完成。

max_age 最大可设为 1 小时。

写后读行为

应用写入数据库时,Hyperdrive 不会清除或使已缓存的读查询结果失效。后续匹配的 SELECT 可能返回缓存结果,直到配置的 max_age 过期。Hyperdrive 还可在 stale_while_revalidate 窗口内提供结果,同时在后台刷新缓存。

写入仍会到达数据库。Hyperdrive 仅缓存符合条件的读查询响应。

因此应根据每次读操作对新鲜度的要求选择缓存策略:

  • 对可容忍短暂 stale 的读使用查询缓存。 适用场景包括公开内容、仪表板、搜索结果、产品目录等高流量读,写入后短延迟可接受。
  • 当短 stale 窗口可接受时,降低 max_agestale_while_revalidate 保持查询缓存开启,同时缩短 Hyperdrive 可提供旧结果的时间。
  • 对必须最新的读使用禁用缓存的 Hyperdrive 配置。 创建第二个带 --caching-disabled 的 Hyperdrive 配置,与缓存配置一起绑定,将这些读路由到禁用缓存的绑定。适用场景包括认证、会话、权限、账单状态、管理设置以及写入后立即读。示例请参阅禁用缓存
  • 仅当大多数读必须最新时,才全局禁用查询缓存。 禁用缓存时仍可获得 Hyperdrive 的连接池和快速连接建立。

若对象关系映射(ORM)库或认证库拥有 SQL,为缓存和禁用缓存的 Hyperdrive 绑定创建独立的数据库客户端。将禁用缓存的客户端传给需要最新读的库或模块,缓存客户端用于可容忍配置 stale 窗口的读。

禁用缓存

使用 Wrangler CLI 的 --caching-disabled 选项,按 Hyperdrive 配置禁用缓存。

对同一数据库创建单独的禁用缓存 Hyperdrive 配置:

npx wrangler hyperdrive create my-database-fresh --connection-string="<DATABASE_CONNECTION_STRING>" --caching-disabled

关闭现有 Hyperdrive 配置的缓存:

npx wrangler hyperdrive update <HYPERDRIVE_CONFIG_ID> --caching-disabled

单个应用可配置多个 Hyperdrive 连接:一个为热门查询启用缓存,第二个用于不应使用查询缓存的最新读。

对同一数据库使用多个 Hyperdrive 配置时,需考虑所有配置到源数据库的总连接数。请参阅调整连接池

例如,使用数据库驱动:

index.tsts
export default {
	async fetch(request, env, ctx): Promise<Response> {
		// Create clients inside your handler — not in global scope
		const client = postgres(env.HYPERDRIVE.connectionString);
		// Use the cache-disabled binding for auth, permissions, and reads after writes.
		const clientNoCache = postgres(env.HYPERDRIVE_CACHE_DISABLED.connectionString);
		// ...
	},
} satisfies ExportedHandler<Env>;
index.tsts
export default {
	async fetch(request, env, ctx): Promise<Response> {
		// Create connections inside your handler — not in global scope
		const connection = await createConnection({
			host: env.HYPERDRIVE.host,
			user: env.HYPERDRIVE.user,
			password: env.HYPERDRIVE.password,
			database: env.HYPERDRIVE.database,
			port: env.HYPERDRIVE.port,
		});
		// Use the cache-disabled binding for auth, permissions, and reads after writes.
		const connectionNoCache = await createConnection({
			host: env.HYPERDRIVE_CACHE_DISABLED.host,
			user: env.HYPERDRIVE_CACHE_DISABLED.user,
			password: env.HYPERDRIVE_CACHE_DISABLED.password,
			database: env.HYPERDRIVE_CACHE_DISABLED.database,
			port: env.HYPERDRIVE_CACHE_DISABLED.port,
		});
		// ...
	},
} satisfies ExportedHandler<Env>;

PostgreSQL 和 MySQL 的 Wrangler 配置相同。

{
	"hyperdrive": [
		{
			"binding": "HYPERDRIVE",
			"id": "<YOUR_HYPERDRIVE_CACHE_ENABLED_CONFIGURATION_ID>",
		},
		{
			"binding": "HYPERDRIVE_CACHE_DISABLED",
			"id": "<YOUR_HYPERDRIVE_CACHE_DISABLED_CONFIGURATION_ID>",
		},
	],
}
[[hyperdrive]]
binding = "HYPERDRIVE"
id = "<YOUR_HYPERDRIVE_CACHE_ENABLED_CONFIGURATION_ID>"

[[hyperdrive]]
binding = "HYPERDRIVE_CACHE_DISABLED"
id = "<YOUR_HYPERDRIVE_CACHE_DISABLED_CONFIGURATION_ID>"

后续步骤

这篇文档对您有帮助吗?