Microsoft Fabric Delta Lake Spark Performance remediate
Systematic workflows for diagnosing and resolving Apache Spark and Delta Lake performance issues in Microsoft Fabric Lakehouse environments.
When to Use This Skill
Activate when the user mentions any of the following:
- Spark job is slow, taking too long, or timing out
- Small file problem, too many small files, file fragmentation
- Data skew, straggler tasks, unbalanced partitions
- Out of memory (OOM) errors on driver or executor
- Shuffle spill, excessive shuffle read/write
- OPTIMIZE, VACUUM, bin-compaction, or table maintenance
- V-Order, Z-Order, or Parquet optimization
- Resource profiles: writeHeavy, readHeavyForSpark, readHeavyForPBI
- Autotune, Adaptive Query Execution (AQE), broadcast join thresholds
- Native Execution Engine configuration
- Streaming performance, microbatch tuning, checkpoint issues
- Spark pool sizing, autoscale, dynamic executor allocation
- Direct Lake performance tied to Delta table structure
- Capacity throttling, TooManyRequestsForCapacity errors
Prerequisites
- Microsoft Fabric workspace with Data Engineering or Data Science experience
- Apache Spark notebooks or Spark Job Definitions
- Lakehouse with Delta tables
- Appropriate Fabric capacity SKU (F2 through F2048)
Quick Diagnostic Workflow
When a user reports slow Spark performance, follow this triage sequence:
Step 1: Identify the Symptom Category
| Symptom |
Likely Root Cause |
Jump To |
| Job runs much longer than expected |
Data skew or small files |
Step 2 |
| OOM error on driver |
collect(), toPandas(), or large broadcast |
diagnostic-checklist.md |
| OOM error on executor |
Wide joins, large shuffles, insufficient memory |
diagnostic-checklist.md |
| Many tasks, most finish fast, few stragglers |
Data skew |
diagnostic-checklist.md |
| High shuffle read/write in Spark UI |
Missing broadcast join or too many partitions |
diagnostic-checklist.md |
| Query reads thousands of small files |
Small file problem, needs OPTIMIZE |
Step 3 |
| Capacity throttled (HTTP 430) |
Too many concurrent jobs for SKU |
spark-configurations.md |
| Streaming lag increasing |
Microbatch interval or partition mismatch |
diagnostic-checklist.md |
Step 2: Check for Data Skew
Run the diagnostic script to detect skew in a target table:
# Quick skew detection
df = spark.read.format("delta").table("your_table")
df.groupBy("partition_column") \
.count() \
.orderBy(F.desc("count")) \
.show(20)
If the top partition has 10x+ more rows than the median, apply skew mitigation. See diagnostic-checklist.md for remediation steps.
Step 3: Check File Health
# Check file count and sizes for a Delta table
from delta.tables import DeltaTable
dt = DeltaTable.forName(spark, "your_table")
detail = spark.sql("DESCRIBE DETAIL your_table")
detail.select("numFiles", "sizeInBytes").show()
# Check for small files (< 32MB)
files_df = spark.sql("DESCRIBE DETAIL your_table")
If file count is high relative to data volume (e.g., >1000 files for <10GB), run OPTIMIZE. See table-maintenance-guide.md.
Step 4: Verify Spark Configuration
Check that the environment has an appropriate resource profile:
# Check current resource profile
print(spark.conf.get("spark.fabric.resourceProfile", "not set"))
# Check key write/read settings
configs = [
"spark.sql.parquet.vorder.default",
"spark.databricks.delta.optimizeWrite.enabled",
"spark.databricks.delta.optimizeWrite.binSize",
"spark.sql.shuffle.partitions",
"spark.sql.autoBroadcastJoinThreshold",
"spark.sql.files.maxPartitionBytes",
"spark.databricks.optimizer.adaptive.enabled"
]
for c in configs:
try:
print(f"{c} = {spark.conf.get(c)}")
except:
print(f"{c} = (default)")
See spark-configurations.md for recommended values per workload type.
Step 5: Apply Fix and Validate
After identifying the root cause, apply the appropriate fix from the references:
Available Scripts
Available Templates
Key Principles
Profile before optimizing — Use Spark UI metrics and the diagnostic script before changing configurations. Most performance issues trace to data layout, not Spark settings.
Match resource profile to workload — Write-heavy ETL should use writeHeavy (V-Order off, stats collection off). Read-heavy analytics should use readHeavyForSpark or readHeavyForPBI (V-Order on, Optimized Write on).
Right-size files first — Target ~128MB–1GB per Parquet file. Use OPTIMIZE regularly for tables with frequent writes. Streaming tables need more frequent compaction.
Partition wisely — Only partition tables over 1TB. Use low-cardinality columns (< 200 distinct values). Over-partitioning creates the small file problem.
Enable AQE — Adaptive Query Execution handles skew joins, partition coalescing, and dynamic broadcast automatically. Keep it enabled.
VACUUM safely — Always retain at least 7 days. Shorter retention can break time travel and concurrent readers.
References
- Diagnostic Checklist — Step-by-step remediate for OOM, skew, shuffle, and streaming issues
- Spark Configurations Guide — Resource profiles, autotune, AQE, pool sizing, and capacity limits
- Table Maintenance Guide — OPTIMIZE, VACUUM, V-Order, Z-Order, and Optimized Write deep dive
1---2name: fabric-delta-spark-perf3description: Troubleshoot and optimize Delta Lake and Apache Spark performance in Microsoft Fabric. Use when diagnosing slow Spark jobs, small file problems, data skew, shuffle bottlenecks, out-of-memory errors, V-Order tuning, OPTIMIZE/VACUUM operations, partition strategy, resource profile selection (writeHeavy, readHeavyForSpark, readHeavyForPBI), autotune configuration, Native Execution Engine, broadcast joins, AQE (Adaptive Query Execution), or when Spark notebooks or Spark Job Definitions run slower than expected in Fabric Lakehouse workloads.4---5
6# Microsoft Fabric Delta Lake Spark Performance remediate
7
8Systematic workflows for diagnosing and resolving Apache Spark and Delta Lake performance issues in Microsoft Fabric Lakehouse environments.
9
10## When to Use This Skill
11
12Activate when the user mentions any of the following:
13
14- Spark job is slow, taking too long, or timing out
15- Small file problem, too many small files, file fragmentation
16- Data skew, straggler tasks, unbalanced partitions
17- Out of memory (OOM) errors on driver or executor
18- Shuffle spill, excessive shuffle read/write
19- OPTIMIZE, VACUUM, bin-compaction, or table maintenance
20- V-Order, Z-Order, or Parquet optimization
21- Resource profiles: writeHeavy, readHeavyForSpark, readHeavyForPBI
22- Autotune, Adaptive Query Execution (AQE), broadcast join thresholds
23- Native Execution Engine configuration
24- Streaming performance, microbatch tuning, checkpoint issues
25- Spark pool sizing, autoscale, dynamic executor allocation
26- Direct Lake performance tied to Delta table structure
27- Capacity throttling, TooManyRequestsForCapacity errors
28
29## Prerequisites
30
31- Microsoft Fabric workspace with Data Engineering or Data Science experience
32- Apache Spark notebooks or Spark Job Definitions
33- Lakehouse with Delta tables
34- Appropriate Fabric capacity SKU (F2 through F2048)
35
36## Quick Diagnostic Workflow
37
38When a user reports slow Spark performance, follow this triage sequence:
39
40### Step 1: Identify the Symptom Category
41
42| Symptom | Likely Root Cause | Jump To |
43|---------|-------------------|---------|
44| Job runs much longer than expected | Data skew or small files | Step 2 |
45| OOM error on driver | `collect()`, `toPandas()`, or large broadcast | [diagnostic-checklist.md](./references/diagnostic-checklist.md#oom-errors) |
46| OOM error on executor | Wide joins, large shuffles, insufficient memory | [diagnostic-checklist.md](./references/diagnostic-checklist.md#oom-errors) |
47| Many tasks, most finish fast, few stragglers | Data skew | [diagnostic-checklist.md](./references/diagnostic-checklist.md#data-skew) |
48| High shuffle read/write in Spark UI | Missing broadcast join or too many partitions | [diagnostic-checklist.md](./references/diagnostic-checklist.md#shuffle-bottlenecks) |
49| Query reads thousands of small files | Small file problem, needs OPTIMIZE | Step 3 |
50| Capacity throttled (HTTP 430) | Too many concurrent jobs for SKU | [spark-configurations.md](./references/spark-configurations.md#capacity-limits) |
51| Streaming lag increasing | Microbatch interval or partition mismatch | [diagnostic-checklist.md](./references/diagnostic-checklist.md#streaming-performance) |
52
53### Step 2: Check for Data Skew
54
55Run the diagnostic script to detect skew in a target table:
56
57```python
58# Quick skew detection
59df = spark.read.format("delta").table("your_table")
60df.groupBy("partition_column") \
61 .count() \
62 .orderBy(F.desc("count")) \
63 .show(20)
64```
65
66If the top partition has 10x+ more rows than the median, apply skew mitigation. See [diagnostic-checklist.md](./references/diagnostic-checklist.md#data-skew) for remediation steps.
67
68### Step 3: Check File Health
69
70```python
71# Check file count and sizes for a Delta table
72from delta.tables import DeltaTable
73dt = DeltaTable.forName(spark, "your_table")
74detail = spark.sql("DESCRIBE DETAIL your_table")
75detail.select("numFiles", "sizeInBytes").show()
76
77# Check for small files (< 32MB)
78files_df = spark.sql("DESCRIBE DETAIL your_table")
79```
80
81If file count is high relative to data volume (e.g., >1000 files for <10GB), run OPTIMIZE. See [table-maintenance-guide.md](./references/table-maintenance-guide.md#optimize-command).
82
83### Step 4: Verify Spark Configuration
84
85Check that the environment has an appropriate resource profile:
86
87```python
88# Check current resource profile
89print(spark.conf.get("spark.fabric.resourceProfile", "not set"))
90
91# Check key write/read settings
92configs = [
93 "spark.sql.parquet.vorder.default",
94 "spark.databricks.delta.optimizeWrite.enabled",
95 "spark.databricks.delta.optimizeWrite.binSize",
96 "spark.sql.shuffle.partitions",
97 "spark.sql.autoBroadcastJoinThreshold",
98 "spark.sql.files.maxPartitionBytes",
99 "spark.databricks.optimizer.adaptive.enabled"
100]
101for c in configs:
102 try:
103 print(f"{c} = {spark.conf.get(c)}")
104 except:
105 print(f"{c} = (default)")
106```
107
108See [spark-configurations.md](./references/spark-configurations.md) for recommended values per workload type.
109
110### Step 5: Apply Fix and Validate
111
112After identifying the root cause, apply the appropriate fix from the references:
113
114| Root Cause | Fix | Reference |
115|------------|-----|-----------|
116| Small files | Run OPTIMIZE with V-Order | [table-maintenance-guide.md](./references/table-maintenance-guide.md#optimize-command) |
117| Stale files bloating storage | Run VACUUM with 7+ day retention | [table-maintenance-guide.md](./references/table-maintenance-guide.md#vacuum-command) |
118| Data skew on joins | Enable AQE skew join + key salting | [diagnostic-checklist.md](./references/diagnostic-checklist.md#data-skew) |
119| Wrong resource profile | Switch to appropriate profile | [spark-configurations.md](./references/spark-configurations.md#resource-profiles) |
120| Driver OOM | Avoid `collect()`, increase driver memory | [diagnostic-checklist.md](./references/diagnostic-checklist.md#oom-errors) |
121| Executor OOM | Increase executor memory, reduce partition size | [diagnostic-checklist.md](./references/diagnostic-checklist.md#oom-errors) |
122| Excessive shuffling | Use broadcast joins for small tables | [diagnostic-checklist.md](./references/diagnostic-checklist.md#shuffle-bottlenecks) |
123| V-Order not applied | Enable at table or session level | [table-maintenance-guide.md](./references/table-maintenance-guide.md#v-order) |
124
125## Available Scripts
126
127| Script | Purpose |
128|--------|---------|
129| [diagnose-delta-performance.py](./scripts/diagnose-delta-performance.py) | Automated diagnostic scan: file health, skew detection, config audit |
130| [table-maintenance.py](./scripts/table-maintenance.py) | Run OPTIMIZE + VACUUM across all tables in a Lakehouse schema |
131
132## Available Templates
133
134| Template | Purpose |
135|----------|---------|
136| [notebook-performance-template.py](./templates/notebook-performance-template.py) | Starter notebook with performance best practices baked in |
137
138## Key Principles
139
1401. **Profile before optimizing** — Use Spark UI metrics and the diagnostic script before changing configurations. Most performance issues trace to data layout, not Spark settings.
141
1422. **Match resource profile to workload** — Write-heavy ETL should use `writeHeavy` (V-Order off, stats collection off). Read-heavy analytics should use `readHeavyForSpark` or `readHeavyForPBI` (V-Order on, Optimized Write on).
143
1443. **Right-size files first** — Target ~128MB–1GB per Parquet file. Use OPTIMIZE regularly for tables with frequent writes. Streaming tables need more frequent compaction.
145
1464. **Partition wisely** — Only partition tables over 1TB. Use low-cardinality columns (< 200 distinct values). Over-partitioning creates the small file problem.
147
1485. **Enable AQE** — Adaptive Query Execution handles skew joins, partition coalescing, and dynamic broadcast automatically. Keep it enabled.
149
1506. **VACUUM safely** — Always retain at least 7 days. Shorter retention can break time travel and concurrent readers.
151
152## References
153
154- [Diagnostic Checklist](./references/diagnostic-checklist.md) — Step-by-step remediate for OOM, skew, shuffle, and streaming issues
155- [Spark Configurations Guide](./references/spark-configurations.md) — Resource profiles, autotune, AQE, pool sizing, and capacity limits
156- [Table Maintenance Guide](./references/table-maintenance-guide.md) — OPTIMIZE, VACUUM, V-Order, Z-Order, and Optimized Write deep dive