A database that must serve both fast single-row transactions and heavy whole-column analytics faces a storage dilemma — rows want a row-store, columns want a column-store, and you cannot have both without either slow rebuilds or stale data; this work from Shanghai Jiao Tong and Tsinghua notices that a CPU naturally reads across memory chips in parallel while processing-in-memory units naturally read down inside a single chip, so it lays out one unified copy of the data along both directions at once, letting the CPU run transactions on rows and in-memory compute units run analytics on columns over the very same data, for 3.4 times and 4.4 times higher throughput than keeping two separate copies.
The argument in one glance
-
Problem
One database, two workloads that want opposite storage layouts
Transactions touch single rows and want a row-store; analytics scan whole columns and want a column-store. A hybrid system cannot get good performance, isolation, and data freshness at the same time, because it must pick a storage format that suits only one of the two.
-
What people did
Keep two copies, or a column-store plus a row delta
Store the data twice in the two formats and rebuild the analytical copy periodically, or keep a primary column-store with a small row-store delta of recent updates that every reader merges in.
-
Why it fell short
Rebuilds go stale; merging breaks isolation
Rebuilding the second copy is so costly it can only run rarely, so analytics see stale data. The column-store-plus-delta design keeps data fresh but forces every analytical scan to also read and merge the slow delta region, so transactions and analytics interfere.
-
This paper's idea
Lay one copy along two access dimensions (PUSHtap)
A CPU reads across memory chips in parallel (good for gathering a row); processing-in-memory units read down inside one chip (good for scanning a column). PUSHtap stores a single unified copy aligned to both directions at once, so the CPU runs transactions on rows and in-memory units run analytics on columns over the same fresh data, with 3.4 times and 4.4 times higher throughput than a two-copy design.
Why this problem is worth solving
Databases increasingly have to be two systems in one, and the two halves pull the physical layout of the data in opposite directions. A database workload splits into two very different kinds of work. Online transaction processing, OLTP, is the everyday churn of a business: read one customer record, update one account balance, insert one order. Each operation touches a single row and usually most of its fields, so it runs fastest when a row’s fields are stored next to each other in memory, a layout called a row-store. Online analytical processing, OLAP, is the reporting and analysis side: sum all sales in a region, average every transaction over a quarter. Each query scans one or a few columns across millions of rows and ignores the rest, so it runs fastest when each column is stored contiguously, a column-store. A hybrid transaction and analytical processing system, HTAP, must serve both. The trouble is that a row-store and a column-store are physically opposite arrangements of the same table, and an HTAP system is judged on three goals at once: workload-specific performance (each side runs on its preferred format), performance isolation (the two do not degrade each other when running together), and data freshness (analytics see the latest committed updates). No conventional single storage layout reaches all three.
The usual escapes each sacrifice one of those three goals, and a promising hardware trend does not by itself fix the bind. Processing-in-memory, PIM, is a hardware idea that puts small compute units directly inside the DRAM memory chips, next to the data. Because those units read the data over the chip’s wide internal wiring instead of the narrow external memory bus, a commercial PIM design reaches several times the effective bandwidth of the CPU and uses far less energy per access — exactly what the memory-bound column scans of analytics need. But PIM has two hard constraints. First, each in-memory compute unit can only directly touch data on its own local chip; reaching data on another chip requires the CPU to move it, which is slow. Second, PIM is controlled coarsely: to run an in-memory computation the CPU hands a whole memory bank over to the PIM units and locks it, blocking its own access for a long time, so PIM has only paid off for big, long-running batch tasks, not for a database that also needs microsecond-level transaction latency. So PIM can accelerate the analytical side, but simply attaching it does not resolve the storage-format dilemma or let transactions and analytics share fresh data without interfering.
What people did before, and where it broke
- Keep a single copy in one format. Store the table once, as either a row-store or a column-store, so analytics always see the latest transactional updates. Where it broke. One format suits only one workload; running the other over it wastes most of the bandwidth it reads, badly degrading that workload’s performance.
- Keep two copies in two formats. Maintain a row-store for transactions and a separate column-store for analytics, each optimal for its side. Where it broke. The column-store copy must be rebuilt from the latest row-store data to stay current, and that rebuild is so expensive it can only run occasionally, so analytics read stale data.
- Keep a column-store plus a row-store delta. Hold a primary column-store and a small row-store delta with the newest updates, so data stays fresh. Where it broke. Every analytical scan must read the fast column-store and then also scan the slow row-store delta and merge the two, so transactions and analytics interfere and isolation is lost.
- Bolt PIM onto a multi-instance design. Put the analytical column-store in PIM memory and accelerate its scans in place. Where it broke. It is still a two-copy design that must rebuild and transfer logs to the PIM memory to stay fresh, so the rebuild overhead still drags analytical performance down.
- The gap. No design gave transactions and analytics each a friendly layout over a single, always-fresh copy without a costly rebuild or a per-query merge. Providing that, by laying one copy along two hardware access directions at once, is what PUSHtap does.
How PUSHtap works
From opposite-format copies to one copy read two ways
-
-
new
-
new
-
new
-
new
-
new
The idea
One copy, read along two directions. PUSHtap’s core observation is that the memory already offers two independent ways to reach the same data: the CPU spreads a single access across many DRAM chips in parallel (perfect for pulling together all the fields of one row), while each in-memory compute unit reads down inside its own chip (perfect for streaming one column). So PUSHtap maps rows to the across-chip direction and columns to the inside-chip direction, and one unified copy becomes row-friendly and column-friendly at once — no second copy, no rebuild, no per-query merge. Deciding what computation to run where based on which processor sits closest to which slice of the data, rather than shuttling data to a fixed compute site, is the same move the near-memory fusion work covered elsewhere on this site makes, partitioning a computation so that each part runs next to the memory it touches instead of dragging that memory across a slow bus.
Keep data fresh with a delta, not a rebuild. Instead of periodically rebuilding a whole analytical copy, PUSHtap uses multi-version concurrency control: new versions of updated rows go into a delta region laid out the same way as the originals, and before an analytical query it builds a compact bitmap snapshot marking which row versions are currently visible, rather than materializing a fresh copy. A background defragmentation, run with the wide in-memory bandwidth, later folds the newest versions back into the main region. Absorbing a stream of updates into a light incremental side structure and periodically merging it back, instead of rewriting the whole dataset, is the same discipline the log-structured merging work covered elsewhere on this site is built on, letting fresh writes land cheaply and paying the reorganization cost in amortized background passes rather than up front on every reader.
Make controlling the accelerator as cheap as a memory access. PIM normally pays a heavy control cost — the CPU hands whole banks over and locks them — which is fatal for a database that also needs quick transactions. PUSHtap extends the memory controller with a small scheduler and polling module and disguises each PIM launch and poll as an ordinary write or read to a reserved address, and it splits every analytical operation into a short load phase and a compute phase so the banks are only locked briefly. Reworking the memory controller itself to reinterpret accesses and hand out control at a finer grain, so a special capability is exposed through the ordinary memory interface, is the same design the software-defined address-mapping work covered elsewhere on this site follows, teaching the controller to treat addresses and accesses flexibly so new behavior is gained without disturbing the processors that issue plain loads and stores.
Following a transaction and an analytical query through PUSHtap
Serving OLTP and OLAP concurrently over one unified copy
A trace of PUSHtap handling an update and a scan on the same table, following the paper's unified-format and MVCC design.
Step 1 of 5
One table laid out along two dimensions
A table is stored once. Each row is aligned across the DRAM chips so the CPU can gather it in parallel, and each column is aligned inside the chips so an in-memory unit can scan it, with a compact layout that wastes little bandwidth to padding.
The same bytes serve rows for the CPU and columns for PIM.
Why it works
- Two access directions come free with the hardware. Because a CPU already interleaves one access across many chips while each in-memory unit already reads inside one chip → the same memory can be read row-wise and column-wise at once → so a single copy can serve both workloads without a second format.
- A compact aligned layout avoids wasted bandwidth. Because a bin-packing layout groups similar-width columns and splits rarely-scanned ones → rows stay aligned across chips and columns aligned inside chips with little padding → so both the CPU and the in-memory units read mostly real data instead of zeros.
- Rotating columns balances the analytical work. Because block-circulant placement rotates which chip holds each column from block to block → a frequently-scanned hot column is spread evenly over all the in-memory units → so no single unit becomes a bottleneck and the parallel bandwidth is fully used.
- A delta plus a bitmap snapshot keeps data fresh cheaply. Because new versions go into a same-layout delta region and visibility is captured in a small bitmap → analytics see the latest committed data without any full rebuild → so freshness no longer costs a stale, infrequent copy.
- Disguised, fine-grained control lets both share the banks. Because PIM commands are issued as ordinary memory accesses and operations are split into short load and compute phases → the banks are locked only briefly instead of for whole batch jobs → so transactions and analytics run concurrently with strong isolation.
What it costs (trade-offs and scope)
- It needs hardware changes to the memory controller. PUSHtap extends a commercial general-purpose PIM design with a scheduler and polling module and a launch-and-poll interface. It is a hardware and software co-design evaluated in simulation, not a change you can deploy on today’s stock servers by software alone.
- The compact layout depends on knowing the workload. The bin-packing layout distinguishes frequently-scanned key columns from rarely-scanned ones and uses a threshold tuned toward OLTP or OLAP. If the query mix shifts substantially, the chosen layout and threshold may no longer be ideal.
- Freshness still costs some snapshot and defragmentation work. Avoiding a rebuild is not free: each query pays to update its visibility bitmap, and periodic defragmentation pauses transactions briefly to fold versions back. The paper reports this overhead as modest — around a tenth of the analytical work — but it is not zero.
- A brief bank lock still blocks the CPU. During an analytical load phase the CPU’s normal access to that bank is blocked, on the order of a few hundred microseconds in the design. That is short enough for many real-time databases but not truly free concurrency.
- The headline gains are versus a specific baseline, in simulation. The 3.4 times and 4.4 times improvements are against a multi-instance PIM-based design in the authors’ simulated system; different baselines, benchmarks, or a real implementation would shift the numbers.
- It targets in-memory, single-instance HTAP. The design assumes the working set fits in the PIM-equipped memory of one instance; scaling across many machines, or to data far larger than memory, would need additional mechanisms beyond this work.
The evaluation
Three ways to store one table for both transactions and analytics
| Property | Single copy, one format | Two copies or column plus delta | PUSHtap unified format |
|---|---|---|---|
| Number of physical copies | |||
| Per-workload performance | |||
| Data freshness for analytics | |||
| Isolation of the two workloads | Good (rebuild) or weak (per-query merge) | ||
| Throughput versus a two-copy PIM design | Not applicable |
Check yourself
Check your understanding
1. Why is it hard for one hybrid database to serve both transactions and analytics well?
2. What is the key hardware observation behind PUSHtap's unified layout?
3. How does PUSHtap keep analytics working on fresh data without rebuilding a second copy?
4. What did PUSHtap achieve, and what are the main limits to keep in mind?
Sources
The paper is “PUSHtap: PIM-based In-Memory HTAP with Unified Data Storage Format” by Yilong Zhao, Mingyu Gao, Huanchen Zhang, Fangxin Liu, Gongye Chen, He Xian, Haibing Guan, and Li Jiang, published at ASPLOS 2025, DOI 10.1145/3676642.3736120. The authors are at Shanghai Jiao Tong University, Tsinghua University, the Shanghai Qi Zhi Institute, and related institutions.
This explainer is based on the full text of the paper, obtained from the authors’ arXiv version (arXiv:2508.02309). The problem framing (the HTAP storage-format dilemma between row-store for OLTP and column-store for OLAP, the three goals of workload-specific performance, performance isolation, and data freshness, and why single-copy, two-copy, and column-store-plus-row-delta designs each sacrifice one of them; the background on processing-in-memory with compute units inside DRAM chips, its higher internal bandwidth, its limitation to local-chip access, and its coarse-grained bank-locking control), the PUSHtap design (the two-dimensional access insight of mapping rows to the CPU’s across-device interleaved access and columns to the in-memory units’ inside-device access; the compact aligned bin-packing format with key and normal columns and a width threshold; the block-circulant data placement for load balance; the multi-version concurrency control with a delta region, bitmap snapshots, and defragmentation; and the extended memory controller with scheduler and polling module that disguises launch and poll as memory accesses and splits operations into load and compute phases), and the results (3.4 times analytical and 4.4 times transactional throughput improvement over a multi-instance PIM-based design, and the low snapshot-and-defragmentation freshness overhead compared with rebuild-dominated baselines) are all drawn directly from the paper. Background explanations of row-stores and column-stores, memory interleaving, DRAM banks, and multi-version concurrency control are standard and provided to make the paper’s contribution understandable. The evaluation figures are the authors’ simulated results.