Server-side streaming cursors
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 35/100
- issue の種類
- 機能追加
- 明瞭さ
- おおむね明確
- 活発さ
- 静か
- 技術スタック
- python, sqlalchemy
調査の方向性
まず、既存の Cursor と AsyncCursor の実装、および SyncResponseContextIterator と AsyncResponseContextIterator の API を読みます。.github/docker/docker-compose.yml をローカルの YDB 統合テストに使用し、fake の session/stream pool を使ったユニットテストを追加します。エクスポートされた同期および非同期のストリーミングカーソルが、セッション所有権、トランザクションの排他性、rowcount、クリーンアップ、README の例を処理できれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Motivation
The current Cursor / AsyncCursor implementation buffers the full
result of a query in memory before fetchone / fetchmany / fetchall
can be called. For large result sets (analytical queries, full-table
scans, ETL-style jobs) this is either infeasible or prohibitively
memory-hungry.
The YDB Query API exposes result sets as a stream
(SyncResponseContextIterator / AsyncResponseContextIterator) —
result sets arrive incrementally over the wire. A DB-API cursor that
consumes that stream lazily would let users process arbitrarily large
results with bounded memory.
Downstream use case: SQLAlchemy
SQLAlchemy has first-class support for server-side cursors via:
Connection.execution_options(stream_results=True)Query.yield_per(N)/select(...).execution_options(yield_per=N)
For these to work, the DB-API driver must expose a cursor that fetches
from the server incrementally rather than materialising everything up
front. Without a streaming cursor on our side, SQLAlchemy users can't
use yield_per / stream_results against YDB and have to either page
manually or blow up memory.
Equivalents in other drivers:
psycopg2— named (server-side) cursors:conn.cursor(name="...")psycopg(v3) —conn.cursor(name="...")/ClientCursorvs
ServerCursorasyncpg— cursor objects returned fromconn.cursor(query)inside
a transaction
Proposed API
Expose a streaming variant through an extra kwarg on Connection.cursor:
with connection.cursor(stream_results=True) as cur:
cur.execute("SELECT ... FROM huge_table")
for row in iter(cur.fetchone, None):
...
And for async:
async with async_connection.cursor(stream_results=True) as cur:
await cur.execute("SELECT ... FROM huge_table")
while (row := await cur.fetchone()) is not None:
...
New public classes: StreamCursor, AsyncStreamCursor, exported from
ydb_dbapi.
Scope
-
StreamCursor(sync) consumingSyncResponseContextIterator -
AsyncStreamCursorconsumingAsyncResponseContextIterator - Own-session mode (auto-commit, no interactive tx): cursor acquires
a session from the pool for the duration of the stream and
releases on finish / close / error - Interactive-tx mode: stream runs on the connection's tx session,
with exclusivity — while a stream is active no other cursor on
the same connection may execute (would corrupt the tx session);
commit/rollbackshould reject while a stream is running -
rowcountsemantics for streaming (likely-1until drained) -
close()must cleanly terminate a mid-flight stream (cancel +
discard session, or drain) in both sync and async paths - Integration tests against a local YDB (see
.github/docker/docker-compose.yml) - Unit tests with fake session/stream pools
- README documentation for the new flag + both code examples
- SQLAlchemy dialect wiring for
stream_results/
yield_per— likely a follow-up inydb-sqlalchemy, but worth
mentioning here
- 主要言語
- Python
- スター
- 4
- フォーク
- 2
- 平均マージ
- 6日 19時間
- マージ済み PR(30日)
- 1
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
似ている issue
-
area: harness bug status: needs-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
Human-Agent-Society/reef#625 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
-
難易度 1/5 1時間未満 初心者へのやさしさ 80/100
learningequality/kolibri#15351 · コメント 2 件 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
-
Name consistency オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
eellak/triplestore#65 · コメント 1 件 ·