Repository navigation
A per-connection prepared-statement cache, and constants every worker may read - #2
Merged
Merged
Conversation
#1) A prepared statement's first execution on a connection parses it under a name of the session's statement cache and describes it, in the same exchange as its Bind and Execute; later executions send only Bind, Execute and Sync. The cache is an LRU of statement_cache_capacity entries (512, pgx's default; 0 turns it off, as does prepared_statements_cache=false), a Close for each statement it gives up going with the next exchange. A kept statement the server refuses to bind as out of date - 26000, 0A000 (cached plan must not change result type), class 42, or class 22 with parameters - is given up and the query prepared anew once, when the error left no transaction block aborted. DISCARD ALL and DEALLOCATE ALL empty the cache, and DDL on the same connection gives up every kept statement, whose parameter types were inferred against the schema before it. Unprepared statements keep the unnamed Parse.
They are only read, from whichever worker a connection is opened or a range is bound on; as Arrays each was a #148 reach warning in every parallel block that opens a connection.
std's Logger is not Share: level=, backend= and for change it in place,
and a connection logs from whichever worker its task runs on. SharedLog
holds Log.for(source) in a Mutex and builds a message only when the
logger takes its severity. The tests set the backend on Log.for("pg"),
the same logger.
DECODERS was a Hash every column read looked up and register_decoder wrote, from any thread. Registrations now go into a registry behind a Mutex, counted by an Atomic, which builds a DecoderTable of them - the OIDs sorted in a List, their decoders in another - when first asked after one. A connection keeps the table it was given and asks again only after a registration, so a column is read without a lock; Decoders.from_oid, which records, ranges and typed arrays use for what they hold, takes the lock. The decoders that held their OIDs in an Array hold a List, so a decoder is Share.
README: Prepared statements, statement_cache_capacity, Share decoders, and the crystal-pg differences. CHANGELOG: the unreleased changes, with the measurements on macOS, and why @[SafeReach] is not used.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1.
What
A per-connection prepared-statement cache. A statement's first run on a connection sends Parse under a generated name and Describe statement, together with Bind/Execute/Sync, in one round trip. Later runs send only Bind, Execute and Sync.
statement_cache_capacityentries, default 512 as in pgx. An evicted statement is closed at the start of the next exchange.statement_cache_capacity=0, or iyi-db'sprepared_statements_cache=false. Unprepared statements, BEGIN and COMMIT keep the unnamed Parse.DISCARD ALLandDEALLOCATE ALLempty the cache, and so does anyCREATE,ALTERorDROPon the same connection.Constants are now Share, for parallel code on iyi's multi-core scheduler:
ConnInfo's tables andQUOTEDareLists.LOGand the replication logger sit behind aMutex.DECODERSis a registry that builds a frozen, Share table. Each connection keeps a table, so reading a column takes no lock.@[SafeReach]is not used, so pg still builds on iyi 0.18.0.Compatibility
ArrayDecoder,RecordDecoder,RangeDecoderandMultirangeDecoderreturn a copy of their OIDs.Measured
Tests
iyi test pg: 20 of 21 files pass.pg/pq/authentication_methods_test.iyifails on master too: it needsPGPORTand scram lines inpg_hba.conf.pg/statement_cache_test.iyi:pg_prepared_statements;ALTER TABLEfrom another session, in and out of a transaction;DEALLOCATEandDISCARD;Known limit
A migration from another session that changes a column to a type the value still converts to without error is not detected (e.g.
timestamp→timestamptzon a server not in UTC). pgx has the same limit. The README says to run such migrations with the cache off, or to reconnect after them.