-
Notifications
You must be signed in to change notification settings - Fork 78
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
Add pipeline support #253
base: master
Are you sure you want to change the base?
Add pipeline support #253
Conversation
To use from a connection: result_sets = pg.pipeline do |pipe| pipe.query "SELECT 42" pipe.query "SELECT * FROM posts LIMIT $1", limit end result_sets.scalar(Int32) # => 42 result_sets.read_all(Post) # => [Post(@id=1, ...), ...] WARNING: This commit does not ensure that all result sets are fully consumed.
case frame = conn.expect_frame(PQ::Frame::ParseComplete | PQ::Frame::CommandComplete) | ||
when PQ::Frame::ParseComplete | ||
conn.expect_frame PQ::Frame::BindComplete | ||
when PQ::Frame::CommandComplete | ||
conn.expect_frame PQ::Frame::ReadyForQuery | ||
conn.expect_frame PQ::Frame::ParseComplete | ||
conn.expect_frame PQ::Frame::BindComplete |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know yet why I had to do this. Hoping someone with more understanding of the Postgres wire protocol can drop some hints.
So sorry @jgaskins I missed this being opened completely until just now! I think it'd be cool to get pipelining in for sure. I think your approach here of a different interface for it is probably the only sane way to do it. I could never come up with a safe way to auto-pipeline queries. No exec I think is fine. If we can't figure out the hang, we can maybe put a limit as to how many queries are in the pipe? Mechanism to ensure all result sets are consumed, I don’t have a strong opinion on this. |
This is a rough sketch for query pipelining support. Pipelined queries in most DBs are implemented as:
Benchmark
Time spent on 100k
SELECT 42
queries (lower is better):That's 55% less wall-clock time and 58% less CPU time with
localhost
latency. For databases where latency might be in the 1-2ms range, the difference will probably be orders of magnitude. In fact, it might've been a more dramatic difference but I had to split the pipelines into chunks — see "known issues" below.Usage
Via
crystal-lang/crystal-db
:The API I had in mind with this is that
query_one
,query_all
, andquery_each
becomequery
inside thepipeline
block andread_one
,read_all
, andread_each
when you're consuming results.Known issues/Remaining work to do
exec
support10_000.times { pipe.query "..." }
PG::Connection
?Example:
Closes #155