Takže vaše otázka se nakonec scvrkává na „jak java.sql.PreparedStatement
hraje s PostgreSQL." Viz odpověď na závěr „jak se to hraje s plány připravenými na serveru".
Zde je odpověď:to závisí na ovladači JDBC, který používáte.
TL;DR :v moderních ovladačích serverem připravený příkaz žije, dokud spojení nezemře nebo dokud není příkaz vyřazen jiným (pravidelné vyřazení LRU).
Poznámka:Server PostgreSQL nemůže sdílet připravený příkaz mezi databázovými připojeními, takže nejlepší ovladač JDBC, který může udělat, je ponechat plán v mezipaměti pro každé připojení.
Poznámka:Specifikace JDBC nařizuje použití ?, ?
pro zástupné symboly vazby, zatímco server chce $1, $2
takže ovladače JDBC ukládají do mezipaměti také takzvané analyzované texty SQL.
Existují dva známé ovladače JDBC:pgjdbc a pgjdbc-ng
pgjdbc
https://github.com/pgjdbc/pgjdbc
Od pgjdbc 9.4-1202
při použití PreparedStatement
automaticky ukládá plány na straně serveru do mezipaměti .Poznámka:příkazy se ukládají do mezipaměti, i když close()
PreparedStatement
.Abyste se dostali k přípravě na straně serveru, musíte provést dotaz 5krát (to lze nakonfigurovat pomocí prepareThreshold
).
V současné době je mezipaměť implementována pro každé připojení. Ve výchozím nastavení pgjdbc ukládá do mezipaměti 256 (preparedStatementCacheQueries
) dotazy a až preparedStatementCacheSizeMiB
dotazů. Toto je konzervativní nastavení, takže jej možná budete chtít upravit. Viz dokumentace
pro popis vlastností. Mezipaměť obsahuje jak analyzované, tak serverem připravené příkazy.
problém s githubem:https://github.com/pgjdbc/pgjdbc/pull/319
pgjdbc-ng
https://github.com/impossibl/pgjdbc-ng
Nejsem na pgjdbc-ng, ale vypadá to, že provádí obě analýzy (výchozí velikost mezipaměti je 250 dotazy) a příprava serveru (výchozí velikost mezipaměti je /a> dotazy). Podpora příkazů připravených na straně serveru byla spuštěna 24. února 2014, takže pokud používáte novější verzi, můžete získat ukládání příkazů do mezipaměti.
Poznámka:Pokud omylem použijete velmi dlouhé dotazy, můžete kliknout na OutOfMemory
protože pgjdbc-ng nemůže vyřadit položky na základě počtu zadržených bajtů.
Mezipaměť je pro jednotlivá připojení, takže se transparentně používá, i když příkazy zavřete.
Nemohu říci mnoho o výkonu pgjdbc-ng, i když od poslední doby, kdy jsem se na něj pokusil hodit jmh, selhal až na náhodné výjimky.
problém s githubem:https://github.com/impossibl/pgjdbc-ng/pull/ 69
Plány připravené serverem
PostgreSQL má PREPARE
a DEALLOCATE
příkazy, které odkazují na příkaz při odesílání EXEC
přes drát. Optimalizuje dvě věci:
- Při použití
PREPARE
d (jinými slovy serverem připravený), klient nemusí posílat text dotazu znovu a znovu. Odešle pouze krátký název dotazu a hodnoty pro proměnné vazby. - Od verze 9.2 se databáze stále pokouší přeplánovat prvních několik spuštění dotazu. Dělá to proto, aby vyzkoušelo, zda dotaz potřebuje více plánů nebo zda je obecný plán dostatečně dobrý. Nakonec (okamžitě, pokud dotaz nemá žádné parametry), databáze může přejít na obecný plán .
- Od 12. roku existuje nastavení, které vynutí provádění VŠECH příkazů připravených na serveru s obecnými nebo vlastními plány:režim_plánovací_mezipaměti
=
auto | force_custom_plan | force_generic_plan
Jinými slovy PreparedStatement
optimalizuje jak analýzu dotazů na straně JDBC, tak plánování dotazů na straně databáze.
Více informací zde:http://blog.endpoint .com/2014/04/custom-plans-prepared-statements-in.html
Připravené příkazy v PL/pgSQL
Podle dokumentace se PostgreSQL ukládá do mezipaměti plány pro dotazy používané v PL/pgSQL. To se stane po několika spuštěních (3 nebo 5, nepamatuji si přesný práh), takže po vytvoření uložené procedury to může být trochu pomalé, ale pak se přepne na plány uložené v mezipaměti (za předpokladu, že databáze souhlasí s použitím obecného plánu pro konkrétní dotaz).
Jinými slovy, abyste dosáhli „plánů provádění uložených v mezipaměti“, musíte buď použít aktuální ovladač JDBC, nebo můžete všechny své dotazy zabalit do uložených procedur. Volání procedury se přeplánuje při každém spuštění, ale samotné volání je obvykle mnohem kratší než dotazy, které tvoří proceduru.