fabric-pyspark-perf-remediate — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited fabric-pyspark-perf-remediate (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Systematic guide for diagnosing and resolving Apache Spark performance problems in Microsoft Fabric Data Engineering workloads, including notebooks, Spark Job Definitions, and pipeline activities.
Activate when encountering any of these scenarios:
Follow this triage sequence to identify the root cause:
Use these indicators to classify your performance issue:
Shuffle Bottleneck: Shuffle read/write bytes are large (>1 GB per stage), many tasks in the stage, high GC time. Fix with broadcast joins, reduced shuffle partitions, or pre-partitioned data. See shuffle-and-join-optimization.md.
Data Skew: One or few tasks take 10x longer than median, input size per task is highly uneven, some tasks process GBs while others process MBs. Fix with salting, repartitioning, or adaptive query execution. See data-skew-resolution.md.
Memory Pressure / OOM: Executor lost errors, "Container killed by YARN for exceeding memory limits", excessive GC time (>10% of task time), disk spill. Fix with memory configuration, caching strategy, or partition sizing. See memory-and-spill-tuning.md.
Small Files / Delta Compaction: Write operations produce thousands of small Parquet files, reads are slow due to file listing overhead, table maintenance never run. Fix with OPTIMIZE, Optimized Write, or streaming trigger intervals. See delta-table-optimization.md.
Capacity / Compute Sizing: Jobs queued for long periods, capacity utilization consistently above 80%, throttling messages in monitoring. Fix with pool sizing, resource profiles, or autoscale billing. See fabric-compute-tuning.md.
# Shuffle partition count - default is 200, tune to data volume
spark.conf.set("spark.sql.shuffle.partitions", "auto")
# Broadcast join threshold - default 10MB, increase for medium tables
spark.conf.set("spark.sql.autoBroadcastJoinThreshold", "50m")
# Max partition bytes - default 128MB, increase for fewer larger partitions
spark.conf.set("spark.sql.files.maxPartitionBytes", "256m")
# Enable Optimized Write for Delta
spark.conf.set("spark.microsoft.delta.optimizeWrite.enabled", "true")
# Enable autotune (preview, Runtime 1.1/1.2 only)
spark.conf.set("spark.ms.autotune.enabled", "true")
# Enable native execution engine
spark.conf.set("spark.native.enabled", "true")
# VOrder for read-optimized scenarios (Power BI, SQL endpoint)
spark.conf.set("spark.sql.parquet.vorder.default", "true")| Profile | Best For | VOrder | Key Behavior |
|---|---|---|---|
writeHeavy | ETL, ingestion, streaming | Off | Optimized throughput for writes (new workspace default) |
readHeavyForSpark | Interactive queries, EDA | On | Optimized for Spark read operations |
readHeavyForPBI | Power BI, SQL endpoint | On | Optimized for downstream BI consumption |
Resource profiles are set at the environment level in Workspace Settings > Data Engineering/Science > Spark Settings.
Autotune automatically adjusts three key configurations per query using ML:
| Setting | Default | What Autotune Optimizes |
|---|---|---|
spark.sql.shuffle.partitions | 200 | Partition count for shuffles |
spark.sql.autoBroadcastJoinThreshold | 10 MB | Broadcast join size threshold |
spark.sql.files.maxPartitionBytes | 128 MB | Max bytes per read partition |
Requirements: Runtime 1.1 or 1.2, not compatible with high concurrency mode or private endpoints. Needs 20-25 iterations to learn optimal config. Targets repetitive queries running >15 seconds.
Run these in a Fabric notebook to gather performance data:
Collecting large datasets to the driver: df.collect() or df.toPandas() on large DataFrames causes OOM. Use .limit(), .take(), or write to Delta instead.
Using `repartition()` before write when Optimized Write is available: Optimized Write handles partition optimization automatically, making explicit repartition() calls redundant and expensive.
Never running OPTIMIZE on Delta tables: Over time, append-heavy tables accumulate small files. Schedule OPTIMIZE (and optionally VACUUM) as maintenance.
Caching DataFrames that are used only once: .cache() or .persist() consume memory/storage. Only cache DataFrames referenced multiple times in the same session.
Using Python UDFs instead of native Spark functions: Python UDFs serialize data between JVM and Python, causing major overhead. Prefer pyspark.sql.functions or Pandas UDFs for vectorized operations.
Ignoring partition pruning: Reading Delta tables without filter predicates on partition columns forces full table scans. Always filter on partition columns when possible.
Problem: Notebook hangs on first cell. Fix: Check if the Spark session is waiting for cluster allocation. Verify capacity is not fully utilized in Monitoring Hub. Consider starter pools for faster spin-up.
Problem: java.lang.OutOfMemoryError: Java heap space on driver. Fix: Reduce collect() size, increase driver memory in environment settings, or switch to writing results to a table instead of returning to the driver.
Problem: Stage with 200 tasks where 1 task takes 30 minutes and rest take 30 seconds. Fix: Classic data skew. See data-skew-resolution.md for salting and repartitioning techniques.
Problem: Write operation produces 10,000+ small files. Fix: Enable Optimized Write: spark.conf.set("spark.microsoft.delta.optimizeWrite.enabled", "true"). Run OPTIMIZE on the table afterward. See delta-table-optimization.md.
Problem: Job ran fine last week but is slow now. Fix: Check Delta table history for data volume growth. Run DESCRIBE HISTORY table_name and check OPTIMIZE history. Also check if workspace resource profile changed.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.