INTEGRITY Dokumentace

Ukládání dotazů do mezipaměti

Když je zapnuto ukládání dotazů do mezipaměti, Hyperdrive automaticky ukládá do mezipaměti ty čtecí dotazy z vašeho Workeru, které lze cachovat. Tím se snižuje zátěž databáze a u často opakovaných dotazů odpadá síťová cesta do databáze a zpět. Ukládání dotazů do mezipaměti je ve výchozím nastavení zapnuté.

Co Hyperdrive ukládá do mezipaměti?

Hyperdrive využívá databázové protokoly k rozlišení mutujícího dotazu (dotazu, který do databáze zapisuje) od nemutujícího dotazu (dotazu pouze pro čtení). Hyperdrive ukládá do mezipaměti odpovědi způsobilých dotazů pouze pro čtení a zápisy do mezipaměti neukládá.

Kromě určení rozdílu mezi SELECT a INSERT, Hyperdrive navíc analyzuje databázový protokol wire a podle něj rozlišuje, zda jde o dotaz měnící data, nebo nikoli.

Do mezipaměti by se například ukládal čtecí dotaz, který naplňuje hlavní stránku zpravodajského webu:

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

Mutující dotazy (včetně INSERT, UPSERT, nebo CREATE TABLE) a dotazy, které používají funkce označené jako volatile ↗ nebo stable ↗ databází PostgreSQL se neukládají do mezipaměti:

-- 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;

Běžné funkce PostgreSQL, které jsou nelze ukládat do mezipaměti patří:

Funkce Kategorie volatility PostgreSQL V mezipaměti
NOW() STABLE Ne
CURRENT_TIMESTAMP STABLE Ne
CURRENT_DATE STABLE Ne
CURRENT_TIME STABLE Ne
LOCALTIME STABLE Ne
LOCALTIMESTAMP STABLE Ne
TIMEOFDAY() VOLATILE Ne
RANDOM() VOLATILE Ne
LASTVAL() VOLATILE Ne
TXID_CURRENT() STABLE Ne

Pouze funkce označené jako IMMUTABLE databází PostgreSQL (funkce, jejichž návratová hodnota se pro stejné vstupy nikdy nemění) jsou kompatibilní s ukládáním do mezipaměti v Hyperdrive. Pokud váš dotaz používá STABLE nebo VOLATILE funkci přesuňte její volání do kódu své aplikace a výslednou hodnotu předejte místo toho jako parametr dotazu.

Výchozí nastavení cache

Výchozí chování ukládání do mezipaměti pro Hyperdrive je:

max_age nastavení určuje maximální dobu, po kterou bude odpověď na dotaz poskytována z mezipaměti. Odpovědi uložené v mezipaměti mohou být z ní odstraněny i dříve, pokud se používají jen zřídka.

stale_while_revalidate nastavení umožňuje Hyperdrive po určitou dodatečnou dobu nadále vracet zastaralé výsledky z mezipaměti, zatímco probíhá její revalidace. Ve většině případů by revalidace měla proběhnout rychle.

Můžete nastavit maximální max_age 1 hodiny.

Chování read-after-write

Hyperdrive nemaže ani neinvaliduje výsledky čtecích dotazů uložené v mezipaměti, když vaše aplikace zapisuje do databáze. Pozdější shodný SELECT může vracet výsledek z mezipaměti až do uplynutí nakonfigurované max_age vyprší. Hyperdrive může výsledek poskytovat i během stale_while_revalidate okno, kdy se mezipaměť na pozadí obnovuje.

Zápisy stále probíhají přímo do vaší databáze. Hyperdrive do mezipaměti ukládá pouze odpovědi na čtecí dotazy, které to umožňují.

Znamená to, že strategii ukládání do mezipaměti byste měli volit podle toho, jak aktuální musí být jednotlivá čtení:

Pokud SQL spravuje knihovna pro objektově relační mapování (ORM) nebo autentizační knihovna, vytvořte samostatné databázové klienty pro vazby (bindings) Hyperdrive s mezipamětí a bez mezipaměti. Klienta s vypnutou mezipamětí předejte knihovně nebo modulu, který potřebuje aktuální data, a klienta s mezipamětí použijte pro čtení, u kterých je přijatelné nakonfigurované okno neaktuálnosti dat.

Zakázat ukládání do mezipaměti

Cachování můžete zakázat pro jednotlivé konfigurace Hyperdrive pomocí Wrangler CLI k nastavení --caching-disabled možnost.

Chcete-li pro stejnou databázi vytvořit samostatnou konfiguraci Hyperdrive s vypnutou mezipamětí:

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

Chcete-li vypnout ukládání do mezipaměti u existující konfigurace Hyperdrive:

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

Z jedné aplikace můžete nakonfigurovat více připojení Hyperdrive: jedno, které povoluje ukládání oblíbených dotazů do mezipaměti, a druhé pro aktuální čtení, u kterého se ukládání dotazů do mezipaměti používat nemá.

Pokud pro stejnou databázi používáte více konfigurací Hyperdrive, zohledněte celkový počet origin připojení napříč všemi konfiguracemi. Více informací najdete v Nastavení fondu připojení pro pokyny.

Například pomocí databázových ovladačů:

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>;

Konfigurace Wrangler zůstává stejná jak pro PostgreSQL, tak pro 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>"

Další kroky