-
Notifications
You must be signed in to change notification settings - Fork 151
Use anonymous statement when needed #80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hmm I wasn't aware of that side effect, apologies. The reason to enable prepared statement for all execution was to feed the "row description" to SQLAlchemy result proxy for typing purposes, which is offered only through prepared statement in asyncpg. I'll investigate a bit about how psycopg2 did this and try to find a workaround. |
Apart from query introspection, using prepared statements would only make sense for executemany. Also, asyncpg itself has some issues with pgbouncer — see MagicStack/asyncpg#198. So this is not a critical issue in any way =) |
Yeah exactly 😈
Ah good to know! I'll track in and see how I can be helpful. |
Looks like MagicStack/asyncpg#198 is fixed, I'll check how this can proceed. |
I'm recently reading docs and source code of libpq, psycopg2, SQLAlchemy and asyncpg. Here're some updates (a bit long). First of all, to clarify about prepared statements: according to PostgreSQL docs 52.1.2, other than execute many and introspection, prepared statements are also an essential step "parse" in extended query, which is the default method asyncpg used to execute queries with parameters. Therefore, any SQL (with parameters) sent to asyncpg is internally prepared first in the "parse" step, through a Meanwhile, simple queries without parameters are executed through the simple query interface, which is the only method used by psycopg2 for now. Simple query uses
Prepared statements are stored on PostgreSQL server, and cached by asyncpg. Obviously unnamed prepared statements cannot be cached, because the next prepare action without name would just flush the previously cached prepared statement on the server side, thus making the cache useless. In order to cache prepared statements for normal queries, asyncpg turned unnamed prepared statements into named ones for extended query if cache is enabled. Meanwhile, However, there is PgBouncer in transaction pooling mode. Officially it states not supporting prepared statements, but it does support extended query. So I tested it, and found it true that PgBouncer doesn't "support" prepared statements. But it doesn't forbid to do so, it's only that prepared statements may be messed up badly between transactions. However, if prepared statements stay inside transactions, it is still safe to use them, both named and unnamed. Especially unnamed ones - because you don't need to worry about closing them, it is always the newest and previous ones are just closed. When this comes to asyncpg/GINO who has no information about which exact backend PostgreSQL session it is using (thanks to PgBouncer), it is meaningless to cache prepared statements even if naming them globally unique between connections (OK to create, but still big issue in using, because they are scoped per backend PostgreSQL session). Therefore, it is the right way under PgBouncer transaction pooling mode to disable prepared statement cache in asyncpg, forcing asyncpg to use unnamed prepared statements for extended queries. But of course Coming to this issue itself, MagicStack/asyncpg#198 fixed an internal usage of named prepared statement, making it possible to use normal queries with PgBoucner. Summing this up, GINO should also use unnamed prepared statement for normal queries, if statement cache is disabled. This would be a simple fix (a bit hacky using asyncpg internal API). For future, it may be reasonable for asyncpg to offer introspection information for all APIs - simple queries, normal extended queries, |
…ended query when cache disabled
I'm using pgbouncer with transaction pooling enabled which means no prepared statements.
I'd like to see an option to disable prepared statements.
Actually, I think we should disable them at all because asyncpg has its own statements cache.
The text was updated successfully, but these errors were encountered: