Table design
UseCollapsingMergeTree with a sign Int8 DEFAULT 1 column. This engine enables efficient fork rollbacks: to cancel rows, the target re-inserts them with sign = -1 and ClickHouse merges the pair during background processing.
- Apply
DoubleDelta + ZSTDcodecs to monotonically increasing columns such as block numbers and timestamps. - Use
LowCardinalityfor columns with low cardinality like addresses to reduce storage and speed up filtering. - Store 256-bit integers as
UInt256; serialize JavaScriptBigIntvalues to strings before insertion.
onStart using store.command():
onData
Call store.insert() to queue an insert. The call is non-blocking — inserts fire concurrently and are fully flushed when the target closes:
onRollback
Implement onRollback to handle blockchain forks. It is invoked in two situations:
reason: 'recovery'— on every restart with a saved cursor, to discard writes from a previous crashed or partial runreason: 'fork'— when the stream detects a chain reorganisation
store.removeAllRows() to remove rows past the safe point. On CollapsingMergeTree-family tables with a sign column this re-inserts matching rows with sign = -1 (the only removal mechanism that propagates through materialized views); on other engines it falls back to a lightweight DELETE with a logged warning (requires ClickHouse ≥ 23.3):
Complete example
Docker setup
docker-compose.yml