Stream results instead of fetching the entire set

This commit is contained in:
Bart Broere committed 2026-11-04 14:34:57 +01:00
1 parent eb989c9155
commit dc978fd0fd
9 files changed
+324 -22

No files matched your search

+19
View File
@@ -1,5 +1,24 @@
# Streaming results instead of fetching them fully
## Status
Done for read queries: they run through a cursor, in a transaction of their own
outside an explicit Bolt transaction. On `UNWIND range(1, 3000000) AS i RETURN i,
'some text in every row' AS t`, boltage's peak memory went from 1419 MB to 44 MB, the
first record from 10.8 s to 0.5 s, and the whole query from 44 s to 33 s.
Queries that can write are deliberately still buffered, unlike what this plan
proposes below. The spike found that AGE performs writes as rows are fetched: fetching
2 of 5 rows of `UNWIND ... CREATE ... RETURN` and committing creates 2 nodes. Writes in
a cursor would therefore not be visible to the next query in the transaction, and
their errors would move from `RUN` to `PULL`. Reads have none of this, and have no
need for `MOVE FORWARD ALL`. Any query containing `CREATE`, `MERGE`, `SET`, `DELETE`,
`REMOVE` or `CALL` is buffered, and runs in autocommit as before. The sections on
draining below only apply if write results are ever streamed; that needs a way to
keep write ordering, and write queries rarely return much.
Tests: `tests/streaming_test.py`, plus additions to `tests/smoke_test.py`.
## Problem
`Session._sql` calls `fetchall()` (`boltage/backend.py:178`), `_run_cypher` parses