---
title: "Columnar storage"
description: "Columnar storage is a data layout that groups values from the same column together on disk, rather than storing complete rows contiguously, which speeds up analytical scans and compression."
canonical: "https://motherduck.com/glossary/columnar-storage/"
related:
  - title: "DuckLake Architecture Deep Dive"
    url: "https://motherduck.com/blog/ducklake-architecture-deep-dive/"
  - title: "Database Concepts | MotherDuck Docs"
    url: "https://motherduck.com/docs/concepts/database-concepts/"
  - title: "DuckLake Lakehouse: Getting Started to Going Fast | MotherDuck"
    url: "https://motherduck.com/videos/ducklake-lakehouse-getting-started/"
gated_asset:
  title: "DuckLake on MotherDuck"
  url: "https://motherduck.com/product/ducklake/"
---

# Columnar storage

> Columnar storage is a data layout that groups values from the same column together on disk, rather than storing complete rows contiguously, which speeds up analytical scans and compression.

## Overview

In a columnar layout, all the values for a single column are stored together, rather than each row's fields being stored contiguously as in a traditional row-oriented database. This layout matches how analytical queries actually access data: a query that aggregates `revenue` grouped by `region` only needs those two columns, and a columnar engine can read just those columns from disk while skipping every other column in the table entirely.

<glossary-callout guide="duckdb-cheatsheet-full" />

## Columnar vs. Row-Oriented

Row-oriented storage is efficient when a workload reads or writes whole records at a time — the classic OLTP pattern of fetching one customer's full record. Columnar storage is efficient when a workload scans and aggregates over large numbers of rows but touches only a subset of columns — the classic OLAP pattern. Columnar layouts also compress much better, since values within a single column tend to be far more similar to each other (repeated categories, sorted timestamps, small integer ranges) than values across a whole row.

## DuckDB's Columnar Engine

DuckDB stores tables in **row groups** (chunks of roughly 122,880 rows by default), and within each row group, data for each column is stored separately as a **column chunk**. Each column chunk is compressed independently using whichever lightweight compression scheme (dictionary encoding, run-length encoding, bit packing, or FSST for strings) fits it best, and DuckDB automatically maintains a min-max zone map per column chunk to skip chunks that can't match a filter. This columnar layout, combined with DuckDB's vectorized execution engine, is what lets it scan and aggregate large Parquet-scale datasets efficiently on a single machine.
