In-Memory Column Index (IMCI) adds a column store and in-memory computing layer to PolarDB for MySQL, enabling hybrid transactional and analytical processing (HTAP) on a single cluster — without sacrificing OLTP performance or migrating your data.
Why MySQL needs a column store
MySQL was designed for online transaction processing (OLTP): single-row lookups, concurrent writes, low-latency transactions. As PolarDB clusters routinely store hundreds of terabytes, users increasingly need real-time analytics on the same data that drives their applications. Three architectural approaches have emerged.
MySQL + dedicated AP database
Deploy two separate systems — MySQL for OLTP and a specialized OLAP database for analytics — with a synchronization pipeline between them. You get the best engine for each workload, but the cost is high: two technology stacks to maintain, synchronization latency that keeps analytics data stale, and no straightforward path to real-time consistency.
Multi-replica divergent design
Distributed NewSQL databases like TiDB (starting with version 4.0) assign different storage formats to different replicas within each Raft group. One replica runs TiFlash, a column store, to serve analytical queries; other replicas handle OLTP. Intelligent query routing selects the right replica automatically. This works well for new deployments but requires migrating from MySQL, which introduces compatibility issues.
Integrated hybrid row-column store
The most advanced approach stores both row-oriented and column-oriented data in the same database instance. All major commercial databases use this design:
-
Oracle introduced the Database In-Memory suite in Oracle Database 12c (2013), using in-memory column store with hybrid row-column execution and query optimizations based on materialized expressions and JoinGroup.
-
SQL Server added columnstore indexes in SQL Server 2016 SP1, supporting row-oriented tables, column-oriented tables, and hybrid combinations.
-
IBM Db2 shipped BLU Acceleration in Kepler 10.5 (2013), combining column store, in-memory computing, and data skipping.
All three converged on this design for the same reason: a column store delivers better I/O efficiency (compression, data skipping, column pruning) and better CPU efficiency (cache-friendly access patterns). But column store indexes are sparse — they cannot efficiently locate individual rows the way a B+ tree index can. A hybrid row-column engine resolves this: the row store handles OLTP with precise row-level indexing, while the column store accelerates bulk analytical scans. DRAM's low latency compensates for the performance gap in column store updates.
Why PolarDB needed a new execution engine
PolarDB's capability stack mirrors open source MySQL. While PolarDB handles OLTP efficiently and supports up to 500 TB of data per cluster, complex analytical queries remain slow. The bottlenecks are fundamental to MySQL's architecture:
-
Serial execution model. MySQL's volcano iterator model processes one row at a time. Each row retrieval triggers multiple layers of function calls, including virtual function dispatch. This destroys CPU pipeline efficiency and prevents use of SIMD instructions.
-
No parallel query. MySQL's executor is single-threaded. Parallel query support in MySQL 8.0 covers only basic operations such as
COUNT(*); complex analytical SQL runs serially regardless of how many CPU cores are available. -
Row store I/O waste. When an analytical query needs only 3 columns from a 50-column table, MySQL still reads all 50 columns from disk. Row store format makes selective column access inherently inefficient.
PolarDB's parallel query framework addresses the CPU bottleneck by distributing scan work across multiple threads and aggregating results on the main thread:
Parallel query breaks the single-core ceiling and reduces query time for scan-heavy workloads. But the row store's I/O inefficiency imposes a ceiling that parallel execution alone cannot overcome. Eliminating that ceiling requires a column store.
A column store improves performance at two levels:
-
I/O efficiency. Queries read only the columns they need. Column data compresses with over 10x efficiency compared to row store. Combined with rough indexes (MIN/MAX statistics per data block), large blocks of irrelevant data can be skipped before decompression. In PolarDB's compute-storage separated architecture, less data transferred across the network directly translates to faster query response.
-
CPU efficiency. Column data is stored contiguously, which improves CPU cache hit rates and reduces L1/L2 cache miss stalls. Contiguous column data also enables SIMD vectorization, multiplying single-core throughput.
Key terms
| Term | Definition |
|---|---|
| IMCI | In-Memory Column Index. PolarDB's implementation of a hybrid row-column store. |
| Columnar index | A secondary index in InnoDB that stores column data in columnar format instead of row format. |
| Row group | The unit of data organization in a columnar index. Each row group holds 64,000 rows. |
| Data pack | A single column's data within one row group, stored contiguously and compressed. |
| Rough index | Pre-computed statistics (MIN, MAX, SUM, null count, row count) for each data pack, used to skip irrelevant data packs without decompressing them. |
| In-Memory Column Store Area | The memory region where active data packs are cached for query execution. Column data is compressed on disk and cached here. |
| Degree of parallelism (DOP) | The number of parallel threads used to execute a query. Auto DOP selects this automatically based on system resources. |
| Volcano model | A query execution model where each operator exposes a Next() interface, pulling data from child operators one row (or batch) at a time. |
| Vectorized execution | A variant of the volcano model where each Next() call returns a batch of rows rather than a single row, enabling SIMD acceleration. |
How IMCI works
IMCI combines four technical innovations:
-
Columnar indexes in InnoDB. Create columnar indexes on selected columns using DDL statements. Columnar indexes use column-compressed storage — significantly smaller than row store — and reside in the In-Memory Column Store Area by default. When memory is insufficient, they spill to shared storage.
-
Column-oriented execution engine. PolarDB's executor accesses data in batches of 4,096 rows and applies SIMD instructions to process multiple values in a single CPU operation. All key operators (Scan, Hash Join, Nested Loop Join, Group By) support parallel execution. Compared to MySQL's row executor, the column executor delivers several orders of magnitude higher performance on analytical workloads.
-
Hybrid row-column optimizer. When a query is submitted, the optimizer evaluates the cost of three execution paths — row store serial execution, row store parallel query, and IMCI — and selects the lowest-cost plan. A whitelist mechanism ensures that queries using unsupported column types or operators fall back to the row store automatically, preserving 100% MySQL compatibility.
-
AP/TP workload isolation. Configure a dedicated read-only (RO) node as an analytical node with columnar indexes. Analytical queries run on the RO node using all available CPU and memory, with no impact on OLTP workloads running on read/write (RW) nodes.
Technical architecture
Hybrid row-column optimizer
Column-oriented execution engine
The IMCI execution engine is a complete rewrite, independent of MySQL's row executor. Its goal is to eliminate two fundamental bottlenecks: virtual function overhead per row and inability to parallelize execution.
Vectorized parallel executor
Vectorized expression system
Hybrid row-column store
OLAP performance
For benchmark results, see IMCI performance.