Skip to content

A block of rows in one call - #29

Merged
tamnd merged 1 commit into
mainfrom
dx-fetchmany
Aug 19, 2026
Merged

A block of rows in one call#29
tamnd merged 1 commit into
mainfrom
dx-fetchmany

Conversation

@tamnd

@tamnd tamnd commented Aug 19, 2026

Copy link
Copy Markdown
Owner

fetchmany on zudb.Result, and the DB-API cursor built on it.

The layer had a fetchmany already, and it was a loop over fetchone, so asking for a thousand rows cost a thousand crossings into the engine. Now the native result has the block form: one lock, one crossing, and the position moves once at the end, so a conversion that fails leaves the result where it was rather than half a block further on. Asking for more rows than are left gives what is left. Asking for none gives none, which is what a loop over a page size read from configuration wants. Asking for fewer than none is refused, because an empty list is exactly what the end of the rows looks like and a loop that believed it would stop early and quietly.

fetchall in the DB-API layer goes through the same call now, since len(result) is every row the statement produced and is never fewer than the rows left.

While measuring it, fetchone turned out to be spending most of its time on the wrapper rather than on the rows. _translating() is a generator-based context manager and costs about 1.4 microseconds to enter and leave, which is nine times what reading a row costs; entering it a million times took 1.4 seconds against 155 ms for the million rows. It is written out as a try and an except in fetchone and nowhere else, since that is the one call in this layer a caller makes once per row.

Over a million rows in two columns on this machine:

how time rows a second
fetchone, before 1977 ms 0.5 M
fetchone, after 234 ms 4.3 M
fetchmany(1000) 75 ms 13.3 M
fetchall 125 ms 8.0 M

Blocks beat fetchall and hold a thousand tuples where it holds a million, so it is both the faster way of reading a large result and the one that does not have to fit.

Nine tests, the stub, and a paragraph in the DB-API section of the README. Green locally: ruff, ruff format, clippy, cargo fmt, and the suite.

@tamnd
tamnd merged commit 132321a into main Aug 19, 2026
4 of 11 checks passed
@tamnd
tamnd deleted the dx-fetchmany branch August 19, 2026 12:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant