Databricks

Databricks Query Optimization Patterns: File Sizing, AQE, Join Strategy, and Spill Mitigation

2026-03-26
更新: 2026-03-27
NicheeLab Editorial Team

Databricks query performance is driven mainly by four levers: right-sizing files, leveraging AQE (Adaptive Query Execution), choosing the right join strategy, and avoiding spill (disk overflow). This article walks through the design patterns and parameter settings for each lever, framed for both the Data Engineer Professional exam and real-world production use.

File Size Design

Delta Lake and Parquet file sizes directly drive read performance. Files that are too small inflate metadata overhead and task-startup cost (the Small File Problem), while files that are too large reduce intra-partition parallelism.

Parameter / OperationPurposeRecommended Value
OPTIMIZECompact small files into optimally sized filesTarget size 128MB (default 1GB; tune per table characteristics)
delta.targetFileSizeTarget file size for OPTIMIZE128MB to 256MB (tune based on read patterns)
spark.sql.files.maxPartitionBytesMax bytes per task during reads128MB (default)
spark.sql.files.openCostInBytesEstimated file-open cost4MB (default)
autoOptimize(autoCompact)Auto-compact small files after writesRecommended for streaming-write tables
-- Run OPTIMIZE (can be combined with ZORDER)
OPTIMIZE gold.orders ZORDER BY (customer_id, order_date);

-- Set the target file size via table properties
ALTER TABLE gold.orders
SET TBLPROPERTIES (
  'delta.targetFileSize' = '134217728'  -- 128MB
);

-- Enable autoOptimize
ALTER TABLE silver.events
SET TBLPROPERTIES (
  'delta.autoOptimize.optimizeWrite' = 'true',
  'delta.autoOptimize.autoCompact' = 'true'
);

Set ZORDER BY on the columns that show up most often in filter predicates. ZORDER spatially clusters data by column value to maximize Data Skipping. It is less effective on very high-cardinality columns (like UUIDs), so keep it limited to 3-4 columns.

AQE (Adaptive Query Execution) Configuration Parameters

AQE dynamically re-optimizes query plans using runtime statistics. It is enabled by default on Databricks and automatically performs the following three optimizations:

  • Coalescing Post-Shuffle Partitions: Coalesces shuffle output partitions that turn out to be too small
  • Converting Sort-Merge Join to Broadcast Hash Join: Switches to Broadcast Hash Join when a side proves small enough at runtime
  • Optimizing Skew Joins: Splits partitions skewed toward specific keys to parallelize them
ParameterDefaultDescription
spark.sql.adaptive.enabledtrueEnables/disables AQE as a whole
spark.sql.adaptive.coalescePartitions.enabledtrueEnables/disables coalescing of small partitions
spark.sql.adaptive.coalescePartitions.minPartitionSize1MBMinimum partition size after coalescing
spark.sql.adaptive.advisoryPartitionSizeInBytes64MBAdvisory partition size after coalescing
spark.sql.adaptive.skewJoin.enabledtrueEnables/disables skew-join optimization
spark.sql.adaptive.skewJoin.skewedPartitionFactor5Multiple of the median size used to flag a partition as skewed
spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes256MBAbsolute threshold for declaring a partition skewed
spark.sql.adaptive.autoBroadcastJoinThreshold30MBSize threshold at which AQE switches to Broadcast Join

Join Optimization: How to Choose a Strategy

Spark has three main join strategies, chosen based on table size and data characteristics. With AQE enabled they can switch at runtime, but understanding them at design time is still essential.

Join StrategyWhen It AppliesBenefitCaveat
Broadcast Hash JoinOne side fits under autoBroadcastJoinThresholdNo shuffle; fastest optionBroadcasting a large table can OOM the driver
Sort-Merge JoinDefault when both sides are largeStable; works reliably for large-vs-large joinsSort + shuffle costs are high
Shuffle Hash JoinWhen one side is fairly large but the other fits in memoryNo sort required; can beat Sort-Merge in some casesHeavy memory use; risk of spill
-- Explicitly broadcast a small table (hint syntax)
SELECT /*+ BROADCAST(dim_products) */
  f.order_id,
  f.amount,
  d.product_name
FROM fact_orders f
JOIN dim_products d ON f.product_id = d.product_id;

-- Tune autoBroadcastJoinThreshold
SET spark.sql.autoBroadcastJoinThreshold = 50m;  -- broadcast tables up to 50MB

The BROADCAST hint overrides the optimizer's decision. For joins between a dimension table (tens of thousands to hundreds of thousands of rows) and a fact table (hundreds of millions of rows), the standard play is to put a BROADCAST hint on the dimension side.

Designing Shuffle Partition Counts

spark.sql.shuffle.partitions controls the number of partitions during shuffles. The default is 200, but you should tune it based on data volume.

  • Small data (a few GB or less): 200 is overkill. Reduce the partition count to cut task overhead.
  • Large data (hundreds of GB or more): with 200 partitions, each one is too big and spill kicks in. Increase the partition count.
  • With AQE enabled: coalescePartitions automatically merges small partitions, so it is safe to set this on the high side.
-- Tune the shuffle partition count
SET spark.sql.shuffle.partitions = 400;

-- Advisory partition size when AQE is enabled
SET spark.sql.adaptive.advisoryPartitionSizeInBytes = 128m;

Spill (Disk Overflow) Mitigation

Spill is what happens when shuffle, sort, or aggregation runs out of memory and offloads data to disk. It tanks performance, so designing to minimize spill matters.

MitigationHowEffect
Increase partition countRaise spark.sql.shuffle.partitionsShrinks per-task data so it fits in memory
Add memorySwitch to memory-optimized instance typesExpands per-executor memory capacity
Use Broadcast JoinBroadcast the small side to skip the shuffle entirelyEliminates the shuffle itself
Pre-filter the dataDrop unneeded rows with WHERE before the joinReduces the volume of data shuffled
Skew mitigationEnable AQE skewJoin, or apply a salting techniqueDistributes skewed partitions
-- Metrics to check in the Spark UI
-- Stages > Task Details:
--   Shuffle Spill (Memory): bytes spilled from memory to disk
--   Shuffle Spill (Disk):   bytes written to disk

-- Example mitigations when spill is happening
SET spark.sql.shuffle.partitions = 800;    -- finer-grained partitions
SET spark.sql.adaptive.advisoryPartitionSizeInBytes = 64m; -- smaller AQE advisory size

Leveraging the Photon Engine

Photon is Databricks' native vectorized execution engine that accelerates the Scan, Filter, Aggregation, and Join stages. Just use a Photon-enabled cluster and it kicks in automatically — no SQL rewrites required.

  • Scan: Accelerates columnar Parquet/Delta reads with SIMD instructions
  • Filter/Aggregation: Executes in native C++ code, eliminating JVM GC overhead
  • Join: Hash-table construction is accelerated in native code
  • Caveat: UDFs and Python UDFs are not Photon-supported. Stick to built-in SQL/DataFrame functions to get the most out of Photon.

Optimization Checklist

  • Run OPTIMIZE + ZORDER on tables regularly to keep file sizes around 128MB
  • Enable autoOptimize on streaming tables
  • Run AQE on default-enabled and tune advisoryPartitionSizeInBytes to your data volume
  • Consider a BROADCAST hint when joining against dimension tables
  • Monitor Shuffle Spill (Disk) on the Spark UI Stages tab and redesign any query that spills consistently
  • Use Photon-enabled clusters and write logic with built-in SQL functions whenever possible

Check Your Understanding

Data Engineer Professional

問題 1

A query joining a 1-billion-row fact table to a 50,000-row dimension table is slow. The Spark UI shows that Sort-Merge Join was chosen and Shuffle Spill (Disk) is enormous. Which is the most effective fix?

  1. Add a BROADCAST hint on the dimension table to eliminate the shuffle
  2. Reduce spark.sql.shuffle.partitions to 10 to cut the number of tasks
  3. Set spark.sql.adaptive.enabled to false to disable AQE
  4. Run OPTIMIZE ZORDER on the fact table using non-join-key columns

正解: A

A 50,000-row dimension table is small enough to broadcast. A BROADCAST hint switches the plan to Broadcast Hash Join, which removes the shuffle and the spill with it. Reducing the partition count makes each task larger and worsens spill. Disabling AQE strips out optimization features. Running ZORDER on non-join-key columns has no effect on the join's shuffle/spill behavior.

Frequently Asked Questions

When should OPTIMIZE be executed?

The best timing is after a batch write completes and before downstream queries run. Typically you put an OPTIMIZE task at the end of an ETL job, or schedule it as a daily maintenance job. For streaming-write tables, enabling Databricks autoOptimize reduces the need for manual runs. Running OPTIMIZE too often increases compute cost, so balance frequency against read performance.

Is AQE enabled by default? When would you disable it?

On Databricks Runtime 12.x and later, AQE (spark.sql.adaptive.enabled) is enabled by default. Cases for disabling it are rare: occasionally to exclude AQE effects during benchmarking, or when AQE's partition coalescing hurts a specific query (verified by testing). For normal operations, keep it enabled.

Where can I check whether spill (disk overflow) is happening?

In the Spark UI Stages tab, you can see Shuffle Spill (Memory) and Shuffle Spill (Disk) per task. If Spill (Disk) is non-zero, data is being spilled to disk. You can also check spill metrics on Sort and HashAggregate nodes in the query execution plan on the SQL tab. For queries that consistently spill, consider tuning spark.sql.shuffle.partitions or increasing memory.

Check what you learned with practice questions

Practice with certification-focused question sets

無料で問題を解いてみる
Author

NicheeLab Editorial Team

NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.


Related articles
Databricks

Databricks Certifications: All 7 Exams, Difficulty & Study Plan (2026)

Complete guide to all 7 Databricks certifications — Data Eng...

Databricks

Databricks Exam Difficulty Ranking: All 7 Certs Compared (2026)

Every Databricks certification ranked by difficulty, with st...

Databricks

Databricks Study Guide: Fastest Pass Route & Time Estimates (2026)

How to pass Databricks certifications efficiently. Official ...

Databricks

Databricks Data Engineer Associate: Complete Guide (2026)

Domain-by-domain breakdown of the Databricks Certified Data ...

Databricks

Databricks Data Engineer Professional: Complete Guide (2026)

Tactics for the Databricks Certified Data Engineer Professio...

Browse all Databricks articles (110)
© 2026 NicheeLab All rights reserved.