<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic The Boring Truth Behind a 60% Speedup in Community Articles</title>
    <link>https://community.databricks.com/t5/community-articles/the-boring-truth-behind-a-60-speedup/m-p/163208#M1366</link>
    <description>&lt;H2&gt;How We Cut Refresh Time and Compute Cost by ~60% — the Mechanics, Not Just the Headline&lt;/H2&gt;&lt;P&gt;"We reduced compute costs by 60%" is a great line in a slide deck and a mostly useless one in a technical forum, because it doesn't tell you &lt;EM&gt;why&lt;/EM&gt;. Here's the actual breakdown from a recent Delta Lake performance pass on an enterprise Lakehouse migration, so the number is reproducible logic rather than a marketing stat.&lt;/P&gt;&lt;H3&gt;Start with measurement, not tuning knobs&lt;/H3&gt;&lt;P&gt;The single biggest mistake I see is reaching for OPTIMIZE, broadcast hints, or repartitioning before looking at &lt;EM&gt;why&lt;/EM&gt; a job is slow. Everything below came from reading the Spark UI / query profile first and matching the fix to the actual bottleneck — usually one of: too many small files, a shuffle-heavy join, or partition skew.&lt;/P&gt;&lt;H3&gt;1. Small-file compaction (OPTIMIZE)&lt;/H3&gt;&lt;P&gt;Streaming and incremental Bronze/Silver writes naturally produce lots of small files. Every file-open has overhead, and at scale that overhead dominates scan time.&lt;/P&gt;&lt;PRE&gt;OPTIMIZE silver.entity_table;&lt;/PRE&gt;&lt;P&gt;For frequently-updated tables, scheduling this as a periodic maintenance job (not just ad hoc) matters — file counts creep back up quickly on high-churn tables.&lt;/P&gt;&lt;H3&gt;2. ZORDER for multi-predicate filters&lt;/H3&gt;&lt;P&gt;Once files are right-sized, co-locating related data matters for anything with selective filters across multiple columns:&lt;/P&gt;&lt;PRE&gt;OPTIMIZE gold.reporting_table
ZORDER BY (region, effective_date);&lt;/PRE&gt;&lt;P&gt;Z-ordering is only worth it on columns that are actually used in filter predicates by downstream consumers — check query history before picking columns, don't guess.&lt;/P&gt;&lt;H3&gt;3. Broadcast joins on dimension tables&lt;/H3&gt;&lt;P&gt;Small reference/dimension tables joined against large fact tables were, in several cases, defaulting to a shuffle join because size estimates were off or auto-broadcast thresholds weren't tuned for the actual table sizes. Explicit broadcast hints removed unnecessary shuffle stages entirely:&lt;/P&gt;&lt;PRE&gt;from pyspark.sql.functions import broadcast

result = fact_df.join(broadcast(dim_df), "dim_key")&lt;/PRE&gt;&lt;H3&gt;4. Adaptive Query Execution (AQE) for runtime skew correction&lt;/H3&gt;&lt;P&gt;A handful of joins had a small number of very hot keys — classic skew. Rather than hand-coding salting logic everywhere, enabling AQE let Spark re-optimize join strategy and coalesce shuffle partitions at runtime:&lt;/P&gt;&lt;PRE&gt;spark.conf.set("spark.sql.adaptive.enabled", "true")
spark.conf.set("spark.sql.adaptive.skewJoin.enabled", "true")&lt;/PRE&gt;&lt;P&gt;For the specific joins where AQE's default skew handling wasn't enough, we fell back to explicit salting — but that was the exception, not the starting point.&lt;/P&gt;&lt;H3&gt;5. Predicate pushdown and partition pruning — the "free" wins&lt;/H3&gt;&lt;P&gt;These come mostly for free with Delta once your filters actually target partition columns and your queries are written to let the file-scan layer do the filtering rather than a downstream .filter() after a wide read. Worth an explicit query-plan check (EXPLAIN) rather than assuming it's happening.&lt;/P&gt;&lt;H3&gt;Where the ~60% actually came from&lt;/H3&gt;&lt;P&gt;Roughly, in order of impact on our workloads:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;File compaction removing small-file scan overhead — the single largest contributor&lt;/LI&gt;&lt;LI&gt;Broadcast joins removing shuffle stages on dimension lookups&lt;/LI&gt;&lt;LI&gt;AQE correcting partition skew at runtime without manual salting&lt;/LI&gt;&lt;LI&gt;Right-sized target file size (~128MB–1GB) balancing parallelism against per-file overhead&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;None of these are exotic. The result came from methodically matching each fix to a measured bottleneck rather than applying all of them blindly to every job — some tables only needed compaction, others only needed the join fix.&lt;/P&gt;&lt;H3&gt;A caveat worth stating plainly&lt;/H3&gt;&lt;P&gt;This number is representative of the specific workloads it was measured against, not a platform-wide guarantee — job characteristics (join shape, file churn rate, skew) vary enough that the same fixes won't move every table by the same amount. If you're citing a similar number in your own writeup, I'd recommend keeping the before/after methodology alongside it rather than the headline number alone.&lt;/P&gt;&lt;P&gt;Would be interested to hear what's driven the biggest wins in others' Delta optimization work — skew handling, file sizing, or something else entirely?&lt;/P&gt;</description>
    <pubDate>Thu, 16 Jul 2026 15:55:22 GMT</pubDate>
    <dc:creator>TriambakR</dc:creator>
    <dc:date>2026-07-16T15:55:22Z</dc:date>
    <item>
      <title>The Boring Truth Behind a 60% Speedup</title>
      <link>https://community.databricks.com/t5/community-articles/the-boring-truth-behind-a-60-speedup/m-p/163208#M1366</link>
      <description>&lt;H2&gt;How We Cut Refresh Time and Compute Cost by ~60% — the Mechanics, Not Just the Headline&lt;/H2&gt;&lt;P&gt;"We reduced compute costs by 60%" is a great line in a slide deck and a mostly useless one in a technical forum, because it doesn't tell you &lt;EM&gt;why&lt;/EM&gt;. Here's the actual breakdown from a recent Delta Lake performance pass on an enterprise Lakehouse migration, so the number is reproducible logic rather than a marketing stat.&lt;/P&gt;&lt;H3&gt;Start with measurement, not tuning knobs&lt;/H3&gt;&lt;P&gt;The single biggest mistake I see is reaching for OPTIMIZE, broadcast hints, or repartitioning before looking at &lt;EM&gt;why&lt;/EM&gt; a job is slow. Everything below came from reading the Spark UI / query profile first and matching the fix to the actual bottleneck — usually one of: too many small files, a shuffle-heavy join, or partition skew.&lt;/P&gt;&lt;H3&gt;1. Small-file compaction (OPTIMIZE)&lt;/H3&gt;&lt;P&gt;Streaming and incremental Bronze/Silver writes naturally produce lots of small files. Every file-open has overhead, and at scale that overhead dominates scan time.&lt;/P&gt;&lt;PRE&gt;OPTIMIZE silver.entity_table;&lt;/PRE&gt;&lt;P&gt;For frequently-updated tables, scheduling this as a periodic maintenance job (not just ad hoc) matters — file counts creep back up quickly on high-churn tables.&lt;/P&gt;&lt;H3&gt;2. ZORDER for multi-predicate filters&lt;/H3&gt;&lt;P&gt;Once files are right-sized, co-locating related data matters for anything with selective filters across multiple columns:&lt;/P&gt;&lt;PRE&gt;OPTIMIZE gold.reporting_table
ZORDER BY (region, effective_date);&lt;/PRE&gt;&lt;P&gt;Z-ordering is only worth it on columns that are actually used in filter predicates by downstream consumers — check query history before picking columns, don't guess.&lt;/P&gt;&lt;H3&gt;3. Broadcast joins on dimension tables&lt;/H3&gt;&lt;P&gt;Small reference/dimension tables joined against large fact tables were, in several cases, defaulting to a shuffle join because size estimates were off or auto-broadcast thresholds weren't tuned for the actual table sizes. Explicit broadcast hints removed unnecessary shuffle stages entirely:&lt;/P&gt;&lt;PRE&gt;from pyspark.sql.functions import broadcast

result = fact_df.join(broadcast(dim_df), "dim_key")&lt;/PRE&gt;&lt;H3&gt;4. Adaptive Query Execution (AQE) for runtime skew correction&lt;/H3&gt;&lt;P&gt;A handful of joins had a small number of very hot keys — classic skew. Rather than hand-coding salting logic everywhere, enabling AQE let Spark re-optimize join strategy and coalesce shuffle partitions at runtime:&lt;/P&gt;&lt;PRE&gt;spark.conf.set("spark.sql.adaptive.enabled", "true")
spark.conf.set("spark.sql.adaptive.skewJoin.enabled", "true")&lt;/PRE&gt;&lt;P&gt;For the specific joins where AQE's default skew handling wasn't enough, we fell back to explicit salting — but that was the exception, not the starting point.&lt;/P&gt;&lt;H3&gt;5. Predicate pushdown and partition pruning — the "free" wins&lt;/H3&gt;&lt;P&gt;These come mostly for free with Delta once your filters actually target partition columns and your queries are written to let the file-scan layer do the filtering rather than a downstream .filter() after a wide read. Worth an explicit query-plan check (EXPLAIN) rather than assuming it's happening.&lt;/P&gt;&lt;H3&gt;Where the ~60% actually came from&lt;/H3&gt;&lt;P&gt;Roughly, in order of impact on our workloads:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;File compaction removing small-file scan overhead — the single largest contributor&lt;/LI&gt;&lt;LI&gt;Broadcast joins removing shuffle stages on dimension lookups&lt;/LI&gt;&lt;LI&gt;AQE correcting partition skew at runtime without manual salting&lt;/LI&gt;&lt;LI&gt;Right-sized target file size (~128MB–1GB) balancing parallelism against per-file overhead&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;None of these are exotic. The result came from methodically matching each fix to a measured bottleneck rather than applying all of them blindly to every job — some tables only needed compaction, others only needed the join fix.&lt;/P&gt;&lt;H3&gt;A caveat worth stating plainly&lt;/H3&gt;&lt;P&gt;This number is representative of the specific workloads it was measured against, not a platform-wide guarantee — job characteristics (join shape, file churn rate, skew) vary enough that the same fixes won't move every table by the same amount. If you're citing a similar number in your own writeup, I'd recommend keeping the before/after methodology alongside it rather than the headline number alone.&lt;/P&gt;&lt;P&gt;Would be interested to hear what's driven the biggest wins in others' Delta optimization work — skew handling, file sizing, or something else entirely?&lt;/P&gt;</description>
      <pubDate>Thu, 16 Jul 2026 15:55:22 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/the-boring-truth-behind-a-60-speedup/m-p/163208#M1366</guid>
      <dc:creator>TriambakR</dc:creator>
      <dc:date>2026-07-16T15:55:22Z</dc:date>
    </item>
  </channel>
</rss>

