Skip Describe portal when executing prepared statements #2422
+282
−6
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.
This is a proof of concept for skipping
Describeportal message when executing a prepared statement.Currently, pgx always sends a
Describeportal message when executing a prepared statement. It receives aRowDescriptionmessage in response. This is convenient as result sets always include aRowDescriptionfirst regardless of whether the query was executed with the simple protocol, the extended protocol without a prepared statement, or the extended protocol with a prepared statement.But pgx always
Describeprepared statements when it creates them. So it already has theRowDescription. The only thing it lacks is the format (text or binary) of the result fields as that is specified per execution. But if pgx remembered the formats it requested when it sent the query it could synthesize the completeRowDescriptionwithout needing to ask PostgreSQL to resend it.This proof of concept adds a new method,
*PgConn.ExecPreparedStatementDescription()that tests this approach.Here are results of one of the existing benchmarks adapted to use the new method along with the original method:
There is a tiny improvement in runtime, on the order of a few 100ns to a 1000ns. Per query memory usage and allocations are reduced by an amount significant to this benchmark. Whether it is significant in the context of an application is another question.
It also reduces the amount of network traffic. The test
TestConnExecPreparedStatementDescriptionNetworkUsagemeasures the bytes written and read to the PostgreSQL server using the same query used in the benchmark above when returning a single row.The amount of bytes written to the server only varies by 7 bytes, 54 without
Describeand 61 withDescribe. But the bytes received varies by 238 bytes, 153 withoutDescribeand 391 withDescribe. That is 2.55x received bytes.The percentage change will vary significantly based on the number of columns in the result set, which determines the size of the
RowDescriptionmessage, and the number of rows returned. If only one row is returned it is quite likely thatRowDescriptionis bigger than the actual data. But if many rows are returned then theRowDescriptioncost is insignificant.Considerations for whether to move forward with this approach:
Describeportal message. See https://github.com/postgres/postgres/blob/master/src/interfaces/libpq/fe-exec.c#L1883-L1895. We may run into edge cases with PostgreSQL as no one else may be doing this. In addition, it may cause compatibility issues with semi-compatible databases like CRDB.