Read and write data
The BlockDB Python SDK wraps the three logical table types in corresponding classes:Table for regular tables, BlockTable for Block tables, and TimeTable for Time tables. Each class is a thin wrapper whose methods ultimately delegate to gRPC. Query methods return Python dict or list[dict]; write methods return a job_id.
The three table models and how to choose
Which model you choose depends on your data shape: regular tables for row-level data, Block tables for state and events that change with block height, Time tables for metrics that change with physical time. See Data model.
Regular tables (Table)
For row-level data, with primary-key reads/writes and full-table scans:For large-table retrieval use
scan_iter (streaming, row by row) and avoid list(scan_iter(...)), which would exhaust memory. The SQL you pass is executed as a stream and can handle result sets in the millions.Block tables (BlockTable)
For block-oriented state and events, reading and writing with a block as the anchor:get_state / get_event use current_block as the anchor and automatically inject height ≤ target height, returning the most recent snapshot at or below that height. The current block height must not exceed the table’s consensus height for the result to be correct — see Block State Table and Block Event Table.
Time tables (TimeTable)
For metrics that change with physical time, reading and writing by time bucket:TimeTable performs the 60-second bucket alignment in the SDK: 17:04:35 aligns to 17:05:00, so reads and writes use the same convention. See Time Table.
Advanced writes
-
Conditional updates:
upsert_rowson regular tables acceptscondition=(column, "if_smaller"/"if_larger"), updating only when the new value is smaller/larger. Useful for monotonic values such as balances and heights: -
Batch writes: backfilling millions of rows goes through the S3-staged batch write interfaces, which return a
job_idyou can query or cancel. See Write architecture.