---
title: Databricks Small-File Performance with Delta Lake
canonical: "https://data-driven.com/blog/databricks-performance-fixing-the-small-file-problem-with-delta-lake/"
pubDate: "2020-08-23T00:00:00.000Z"
updatedDate: "2026-08-25T00:00:00.000Z"
description: "A versioned technical walkthrough of partitioning, MERGE, compaction, and validation for a high-volume Delta Lake workload."
tags: [data-lake, advanced, delta-lake, spark]
categories: [databricks]
---

Small files can make a data-lake workload expensive to list, open, and scan. This 2020 implementation converted frequent JSON and CSV drops into Delta tables, then tested partitioning, deduplication, and compaction against the workload's query pattern.

The architecture and code are retained as a dated implementation record. Databricks now automates more file-size and layout work, especially for Unity Catalog managed tables.

## The original ingestion shape

Near-real-time APIs wrote many small files into an Azure Data Lake Storage raw zone. Azure Data Factory then orchestrated Databricks notebooks that parsed the files and wrote Delta tables.

![Delta Lake ingestion architecture](../../assets/blog/2020/08/Delta-Lake-Aquitecture.png)

The design separated the transmission format from the analytical table. That distinction still matters: a format that is convenient for an API response may not be efficient for repeated analytical reads.

## Partitioning followed the query pattern

The implementation derived year, month, and day fields from the source timestamp, then wrote a date-partitioned Delta table.

```python
partitioned_df = source_df \
    .withColumn("year", from_unixtime(col("header_timestamp"), "yyyy")) \
    .withColumn("month", from_unixtime(col("header_timestamp"), "MM")) \
    .withColumn("day", from_unixtime(col("header_timestamp"), "dd"))

partitioned_df.write \
    .partitionBy("year", "month", "day") \
    .format("delta") \
    .mode("append") \
    .save(destination_path)
```

![Date partitioning used in the original Delta Lake implementation](../../assets/blog/2020/08/Partitioning-the-Delta-Lake-1024x155.png)

This is not a universal recommendation. Current Databricks guidance recommends liquid clustering for many new tables and automatic tuning for Unity Catalog managed tables. Partitioning remains a workload-specific choice.

## Deduplication used a bounded MERGE

The source API could return repeated records. The implementation created a row identifier, then limited the merge comparison to recent partitions rather than scanning the full table.

```python
hashed_df = source_df.withColumn(
    "row_sha2",
    sha2(concat_ws("||", *source_df.columns), 256),
)
```

```python
delta_table.alias("current").merge(
    hashed_df.alias("incoming"),
    "current.row_sha2 = incoming.row_sha2 "
    "AND to_date(current.header_timestamp) >= current_date() - INTERVAL 1 DAY",
).whenNotMatchedInsertAll().execute()
```

The key lesson is the boundary, not the exact interval. The team needs a stable identifier and a defensible window for late or repeated records.

## Current maintenance is more automatic

Databricks' <a href="https://docs.databricks.com/aws/en/tables/tune-file-size" target="_blank" rel="noopener noreferrer">current file-size guidance</a> says:

- Unity Catalog managed tables use automatic file-size tuning.
- Optimised writes and auto compaction are enabled for several write operations.
- Predictive optimisation can run `OPTIMIZE` for managed tables.
- Manual repartitioning before a write is not recommended when optimised writes are used.

For current table layout, Databricks also recommends liquid clustering for many workloads. The <a href="https://docs.databricks.com/aws/en/tables/operations/optimize" target="_blank" rel="noopener noreferrer">current `OPTIMIZE` guide</a> describes compaction, clustering, and the cost/performance tradeoff.

## Validate with the workload's own evidence

The original project compared the compacted Delta table with the raw-file path and recorded a material improvement for its selected query. The exact figures are omitted here because the source does not provide the cluster, runtime, query, or repeatable benchmark needed to generalize them.

![Validation chart from the original Delta Lake implementation](../../assets/blog/2020/08/Validation-of-the-Delta-Lake.png)

For a current review, capture table type, runtime, file counts, file-size distribution, query plan, maintenance history, duration, and compute cost. That evidence shows whether a layout change helped this workload rather than promising a universal result.
