← Delta Optimization track

Databricks · Delta Optimization · Lesson 08

Liquid
Clustering.

The modern way to lay out Delta tables for fast queries — it replaces partitioning and Z-ordering, and you can change the layout later without rewriting your data.

GA on DBR 15.4 LTS+ Replaces partitioning + ZORDER Up to 4 keys Verified Jun 2026 docs

The problem it solves

When a table is small, the engine just reads all of it. When a table grows to billions of rows, a query like WHERE country = 'IN' shouldn't have to scan everything — it should read only the files that could contain matching rows and skip the rest. That skipping is the whole game, and it's called data skipping.

Data skipping only works if related rows are physically stored near each other on disk. The old tools for arranging that were partitioning and Z-ordering. Both work, but both are rigid and high-maintenance. Liquid clustering is the replacement.

Analogy
Liquid clustering is like re-shelving a library by the labels people actually search for — and you can re-shelve later without emptying the building. Partitioning nails the shelves to the floor on day one.

Use case
A fast-growing events table you filter by event_type and event_date: CLUSTER BY (event_type, event_date) colocates those rows so a query reads a handful of files — and you can switch keys later with one ALTER TABLE, no full rewrite.

Why it beats the old ways

The one rule to remember Liquid clustering is not compatible with partitioning or ZORDER. You use it instead of them — never alongside.

See it work — data skipping

Below is a table stored as 64 files. Pick a layout, then run a filter and watch which files get scanned vs. skipped. The fewer files scanned, the faster and cheaper the query.

Data-skipping simulator

A 64-file Delta table of customer rows, colored by country.

Files on disk
scanned (must read) skipped (data skipping) clustered file
—
files scanned
—
files skipped
—
data read avoided

This is a simplified illustration of the concept. Real data skipping uses per-file min/max statistics on clustering keys; results depend on data distribution and file sizes.

See it work — change keys with no rewrite

The headline benefit: you can redefine the clustering keys at any time, and existing data is not rewritten until you choose to recluster. Step through the lifecycle to see what each command touches.

Re-key lifecycle

8 files: blue = laid out by k1 (country), amber = laid out by k2 (customer_id). Watch which files move at each step.

laid out by k1 (country) laid out by k2 (customer_id)
1 / 4
step
0
files rewritten this step

Simplified illustration. In reality ALTER TABLE … CLUSTER BY changes only metadata; new writes and incremental OPTIMIZE use the new keys, and OPTIMIZE FULL reclusters historical data.

Two flavors

FlavorSyntaxWhen to use
ManualCLUSTER BY (c1, c2)You already know which columns you filter on most. Pick up to 4.
AutomaticCLUSTER BY AUTOLet Databricks analyze query history and choose. Needs a Unity Catalog managed table + predictive optimization (DBR 15.4 LTS+).

Choosing good keys

The commands you'll actually use

Create a table with clustering (SQL)

SQL-- CLUSTER BY goes right after the column list (and before AS for CTAS)
CREATE OR REPLACE TABLE catalog.schema.customers (
  customer_id BIGINT,
  country     STRING,
  signup_date DATE
)
CLUSTER BY (country, signup_date);   -- up to 4 keys

Create a table with clustering (PySpark / DeltaTable API, DBR 14.3 LTS+)

PYSPARKfrom delta.tables import DeltaTable

# DeltaTable builder with clustering keys
(DeltaTable.create(spark)
    .tableName("catalog.schema.customers")
    .addColumn("customer_id", "BIGINT")
    .addColumn("country", "STRING")
    .addColumn("signup_date", "DATE")
    .clusterBy("country", "signup_date")   # the clustering keys
    .execute())

# Or cluster on write straight from a DataFrame
(df.write.clusterBy("country", "signup_date")
   .saveAsTable("catalog.schema.customers"))

Enable on an existing (unpartitioned) table

SQLALTER TABLE catalog.schema.customers CLUSTER BY (country, signup_date);
-- recluster existing data to the new keys (DBR 16.0+)
OPTIMIZE catalog.schema.customers FULL;

Trigger clustering (incremental)

SQL-- only rewrites what's needed; cheap to run often (every 1-2h for high-churn tables)
OPTIMIZE catalog.schema.customers;
PYSPARKfrom delta.tables import DeltaTable
DeltaTable.forName(spark, "catalog.schema.customers").optimize().executeCompaction()

Change the keys later — no full rewrite

SQL-- metadata-only change; existing files are NOT rewritten
ALTER TABLE catalog.schema.customers CLUSTER BY (customer_id);
-- reorganize ALL existing data to the new keys (can be slow on huge tables; DBR 16.0+)
OPTIMIZE catalog.schema.customers FULL;

Let Databricks pick the keys (AUTO)

SQL-- UC managed table + predictive optimization required
ALTER TABLE catalog.schema.customers CLUSTER BY AUTO;
SHOW TBLPROPERTIES catalog.schema.customers;  -- look for clusterByAuto = true

Convert a partitioned table (DBR 18.1+)

SQLALTER TABLE catalog.schema.customers REPLACE PARTITIONED BY WITH CLUSTER BY (country, signup_date);
OPTIMIZE catalog.schema.customers FULL;

Inspect / turn off

SQLDESCRIBE DETAIL catalog.schema.customers;        -- see clusteringColumns
ALTER TABLE catalog.schema.customers CLUSTER BY NONE;  -- stop clustering

Liquid clustering vs partitioning vs Z-order

AspectLiquid clusteringPartitioningZ-order
Change keys laterYes — no rewriteNo — full rewriteRe-run (rewrites data)
High-cardinality keysDesigned for itPartition explosionOK, benefit drops per col
MaintenanceOPTIMIZE (incremental) / OPTIMIZE FULLCompaction within partitionsOPTIMIZE … ZORDER (not idempotent)
Struct fields as keysYes (dot notation)No (top-level only)Yes (with stats)
Combine with the othersNo — replaces bothZ-order works within partitionsCan't target partition cols
Min runtimeGA DBR 15.4 LTS+ (API 14.3+)All DBRAll DBR
RecommendationDefault for new tablesOnly > 1 TB / legacyLegacy; prefer clustering

Uses, edge cases & limitations

Uses — when to reach for it (and when not)

Edge cases interviewers probe

Limitations (honest constraints)

Quick gotchas