Skip to main content

Lance: Rebuilding columnar storage for random access and AI workloads

19 October 2026
  • News

This is part three in our six-part series exploring alternatives to Apache Parquet. So far we’ve covered Parquet for on-disk storage and Apache Arrow for in-memory processing. Today we look at Lance, an open-source format built to handle the access patterns that Parquet was never designed for.

Parquet was designed around analytical scans, reading a few columns across many rows, as fast as possible. Many modern workloads look different: Machine learning (ML) training shuffles and samples individual rows, feature lookups fetch a handful of records at a time, and embeddings and images sit next to ordinary tabular data.

The underlying storage has changed dramatically too, from spinning disks to NVMe SSDs and cloud object stores. Lance, written in Rust, is designed to take advantage of these shifts.

Blue square chip featuring a smaller centered square and four short tabs extending from each side sits on a white background Explore Apache Arrow

In part two of our six-part series, we explore how Apache Arrow accelerates in-memory analytics through zero-copy data sharing and efficient data processing.

Read part two

Why random access is hard in Parquet

In Parquet, the page is the unit of compression. To read a single value, a reader must fetch and decode the whole page that contains it, which is wasteful when only one value is needed. Nested data makes this problem worse: because Parquet shreds nested structures into several flat columns, one logical lookup can require reads from several column chunks.

Parquet can be tuned for better random access, but at a cost. The Lance authors’ research paper found that a carefully configured Parquet file achieved over 60x better random-access performance than the defaults, but only by trading away scan performance or RAM.

Row group sizing shows the same tension: large row groups suit scans but consume lots of memory when writing large binary objects, while small ones hurt compression and multiply metadata.

Rack mounted servers show multiple green status lights indicating activity in a dimly lit data center with rows of stacked metal chassis and network equipment

Designing for how NVMe actually behaves

On a modern NVMe drive, bandwidth is rarely the bottleneck for point lookups. The drive in the Lance paper’s test setup handled around 850,000 random 4 KiB reads per second. At that scale, what matters is how many separate I/O operations each lookup needs.

Lance’s file format is built around minimizing that number. Its target is at most one I/O operation for a fixed-width column (such as int64 or float64) and at most two for a variable-width column (such as strings), regardless of how deeply the data is nested.

Separating structure from compression

The key idea behind Lance’s encoding is to treat two concerns separately:

  • Structural encoding determines how an array, including its validity and nesting information, is laid out on disk. This decides how many reads a lookup takes.
  • Compressive encoding determines how the resulting buffers are shrunk, using techniques such as bit-packing, dictionary encoding, or general-purpose compression.
Man points with marker at whiteboard while explaining geometric diagrams in a modern open office corridor with exposed ceiling lights and a blurred colleague in the foreground

Lance chooses a structural encoding, which its specification calls a layout, for each page of data. There are five layouts to choose from:

  • Mini-block layout (used for values under 256 bytes) packs values into small chunks of less than 32 KiB of compressed data. Reading a whole chunk to get one value is cheap, so Lance can use any compression here, including “opaque” schemes where individual values can’t be decoded on their own.
  • Full-zip layout (used for larger values, like embeddings) interleaves each value with its structural information in a single buffer. A repetition index maps each row directly to its byte offset, so a single value can be read without touching its neighbors. Only “transparent” compression, where one value can be decoded in isolation, is allowed here.
  • Constant layout stores a page where every value is the same (or null) as that single value.
  • Blob layout, which users must opt into, stores very large objects such as images or video outside the page and keeps only their locations.
  • Sparse layout, available only in the experimental 2.3 format, handles data containing relatively few non-null values.

Lance also drops row groups entirely. Instead, an I/O scheduler splits each column’s reads into appropriately sized requests and runs them in parallel, keeping scan throughput high without a row group size to tune.

More than a file format

Lance is also a table format. Each change to a dataset (an append, a delete, a new column) is committed as a new, immutable manifest pointing to the relevant data files. Deletes go into separate deletion files, and new columns can be added without rewriting existing files. Older versions stay readable, supporting reproducible training runs and easy rollback. Vector and scalar indexes live alongside the data but can be rebuilt independently of it.

Lance reads directly into Arrow’s in-memory format, so DuckDB, Polars, pandas, and PyTorch can work with Lance data without conversion.

Where Lance fits in the ecosystem

One important thing to mention: Lance is now developed as an independent open-source project, separate from LanceDB, the multimodal lakehouse built on the Lance file format.

Lance isn’t a drop-in replacement for Parquet. Parquet’s ecosystem is far broader, with support in nearly every query engine and many independent implementations. Lance’s strength is narrower: datasets that need fast random access, vector search, large binary objects, and built-in versioning. The Lance paper reports that its latest format version often matches or exceeds Parquet’s scan performance while delivering much faster random access, suggesting that the trade-off between scans and lookups isn’t as fundamental as it once seemed.

In our next post, we’ll look at BtrBlocks, a research format that takes a different approach, focusing on fast decompression through cascading lightweight encodings.

Adam Reeve, Open-Source Software Developer

Explore the full series

Part one

Understanding Apache Parquet: How columnar storage powers modern analytics

Hear from one of our Open-Source Software Developers on the engineering behind Apache Parquet and how its columnar architecture enables efficient, high-performance analytics at scale.

Read now
Part two

Apache Arrow: Accelerating in-memory analytics through zero-copy data sharing

Explore how Apache Arrow accelerates in-memory analytics through zero-copy data sharing, columnar memory and hardware-conscious design, and why it works so effectively alongside Apache Parquet.

Read now

Open-Source Software at G-Research

We play an active role in the open-source community, maintaining projects, contributing to essential software and supporting open-source foundations.

Abstract glossy forms flowing and merging across a dark reflective surface creating smooth ripples and undulating contours in monochrome tones

Latest events

  • Quantitative engineering
  • Quantitative research

ETH Zürich quant challenge 2026

27 Oct 2026 ETH Zürich, Switzerland
  • Quantitative engineering
  • Quantitative research

London quant challenge 2026

04 Nov 2026 G-Research office, 1 Soho Place
  • Machine learning
  • Quantitative research

NeurIPS 2026

06 Dec 2026 - 12 Dec 2026 The International Convention Centre, Sydney

Stay up to date with G-Research

Join our talent network

Be the first to hear about new roles and opportunites to join our team.