Per-table layout
ROW, COLUMNAR or HYBRID storage, chosen per table.
Point reads, writes and analytical scans on one engine, with the storage layout chosen per table instead of a second system to ETL into.
The problem
The HTAP tax is two databases. A row store handles point reads and writes well but scans slowly; a column store scans well but is a poor fit for single-row access. So you run both and ship rows between them with CDC and ETL, paying for the lag, the duplication and the reconciliation jobs that keep them honest.
The copy is where correctness goes to die: the analytical side is always behind the operational side, dashboards disagree with the application, and the same question returns a different number depending on which store you ask.
You want one engine where each table’s layout matches how you read it, under one catalog and one SQL surface.
Architecture
Every table declares its own storage profile: a keyed ROW table serves point access, a COLUMNAR table with codecs and indexes serves scans, and both live in the same catalog with nothing shuttling rows between them.
Point access gets a keyed table with STORAGE PROFILE ROW; scans get an append-only table with STORAGE PROFILE COLUMNAR.
Each statement is its own atomic write, in the write-ahead log before it is acknowledged.
Primary-key reads, plus POSTINGS and BLOOM indexes on non-key columns.
GROUP BY, HAVING and COUNT(DISTINCT) over the columnar table, with MINMAX indexes pruning what is not needed.
Examples
CREATE TABLE balances ( chain_id UINT16 NOT NULL, address STRING NOT NULL, token STRING NOT NULL, amount UINT256 NULL, updated_at DATETIME64(3, 'UTC') NULL, balance_index UINT128 NULL, balance_version UINT64 NULL, transfer_count UINT64 NULL, last_transfer_at DATETIME64(3, 'UTC') NULL, activity_index UINT128 NULL, PRIMARY KEY (chain_id, address, token), ATTRIBUTE GROUP holding (amount, updated_at, balance_index, balance_version) VALID BY (balance_index) REVISION BY (balance_version), ATTRIBUTE GROUP activity (transfer_count, last_transfer_at, activity_index) VALID BY (activity_index))MODE VERSIONEDSHARD BY (address) SHARDS AUTOORDER BY (chain_id, address, token);CREATE TABLE transfers ( chain_id UINT16 NOT NULL, token STRING NOT NULL, sender STRING NOT NULL, recipient STRING NOT NULL, amount UINT256 NOT NULL, transferred_at DATETIME64(3, 'UTC') NOT NULL, _index UINT128 NOT NULL, INDEX transfers_ts (transferred_at) USING MINMAX SCOPE HISTORY GRANULE 8192)MODE APPENDSHARD BY (token) SHARDS AUTOPARTITION BY MONTH(transferred_at)ORDER BY (chain_id, token, _index)STORAGE PROFILE COLUMNAR;SELECT address, token, amount, updated_atFROM balancesWHERE chain_id = 1 AND address = '0x9c2e4f1a';The examples use the same two tables on every page. See the SQL reference for full syntax.
Capabilities
ROW, COLUMNAR or HYBRID storage, chosen per table.
Each statement is its own atomic write, durable before it is acknowledged.
Decide how successive writes combine, with REDUCER SUM, MIN, MAX or REPLACE.
MINMAX for ranges, BLOOM for membership, POSTINGS for exact keys.
Operational and analytical tables share one schema and one SQL surface.
Analytical tables are derived from operational ones inside the engine, by transformations.
Learn more
Model an operational table and an analytical table, and query both.