INTEGRITY Документация

Кеширование запросов

Когда кэширование запросов включено, Hyperdrive автоматически кэширует те запросы на чтение от вашего Worker, которые допускают кэширование. Это снижает нагрузку на базу данных и избавляет от сетевого round trip к базе данных при популярных запросах. Кэширование запросов включено по умолчанию.

Что кэширует Hyperdrive?

Hyperdrive использует протоколы базы данных, чтобы отличать изменяющие запросы (запросы, которые выполняют запись в базу данных) от неизменяющих (запросов только на чтение). Hyperdrive кеширует подходящие ответы на запросы только для чтения и не кеширует записи.

Помимо определения разницы между SELECT и INSERT, 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

Запросы, изменяющие данные (включая INSERT, UPSERT, или CREATE TABLE) и запросы, использующие функции, обозначенные как volatile ↗ или stable ↗ в PostgreSQL, не кэшируются:

-- Not cached: mutating queries
INSERT INTO users(id, name, email) VALUES(555, 'Matt', '[email protected]');

-- 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', '[email protected]');

-- 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 Нет

Только функции, обозначенные как IMMUTABLE в PostgreSQL (функции, результат которых не меняется при одинаковых входных данных) совместимы с кэшированием Hyperdrive. Если ваш запрос использует STABLE или VOLATILE функции, перенесите вызов функции в код приложения и передавайте полученное значение в качестве параметра запроса.

Настройки кэширования по умолчанию

Поведение кеширования Hyperdrive по умолчанию:

max_age определяет максимальное время, в течение которого ответ на запрос будет отдаваться из кеша. Закешированные ответы могут быть вытеснены из кеша раньше этого срока, если они используются редко.

stale_while_revalidate позволяет Hyperdrive продолжать отдавать устаревшие результаты из кеша ещё некоторое время, пока выполняется его ревалидация. В большинстве случаев ревалидация происходит быстро.

Можно задать максимальное max_age продолжительностью в 1 час.

Поведение чтения после записи

Hyperdrive не очищает и не сбрасывает кэш результатов запросов на чтение при записи вашим приложением в базу данных. Более поздний совпадающий SELECT может возвращать кэшированный результат до истечения настроенного max_age истекает. Hyperdrive также может отдавать результат в течение stale_while_revalidate интервала, пока кеш обновляется в фоновом режиме.

Запросы на запись по-прежнему поступают в вашу базу данных. Hyperdrive кэширует только ответы на подходящие запросы на чтение.

Это значит, что стратегию кеширования следует выбирать исходя из того, насколько актуальными должны быть данные при каждом чтении:

Если SQL-запросы формирует библиотека объектно-реляционного отображения (ORM) или библиотека аутентификации, создайте отдельные клиенты базы данных для привязок Hyperdrive с включенным и отключенным кешированием. Передайте клиент с отключенным кешированием библиотеке или модулю, которым нужны актуальные данные при чтении, а клиент с включенным кешированием используйте для чтений, допускающих настроенное окно устаревания данных.

Отключить кеширование

Отключите кэширование для отдельной конфигурации Hyperdrive с помощью Wrangler CLI, чтобы задать --caching-disabled опцию.

Чтобы создать для той же базы данных отдельную конфигурацию 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.ts
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.ts
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>;

Конфигурация Wrangler остаётся одинаковой как для PostgreSQL, так и для MySQL.

{
	"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>"

Следующие шаги