Skip to content
Carmel Eve By Carmel Eve Software Engineer II · 2 min read
Optimising DAX: Model Design Comparisons and Testing Tips

Hello again. Over the last few posts in the Optimising DAX series, we've covered how VertiPaq stores data, encoding techniques, cardinality, and relationship costs. In this post, we're putting it all together to compare three common model designs and see how they perform in practice.

The Comparison

During the workshop, we loaded the same data into three different model designs in DAX Studio and compared the results:

Star Schema - Dimension tables (customers, products, dates) linked to a central fact table. Flat Table - Everything denormalised into a single wide table. Header/Detail - Two fact tables linked by a primary key.

Model size comparison: star schema smallest, then flat table, then header/detail

In the example, star schema was the smallest, then flat table, then header/detail. Though it's always worth checking with your specific data!

Why Star Schema Wins

The dimension tables are small and compress well. The fact table contains foreign keys (medium cardinality) and measures. Everything benefits from good compression, and the relationships are through relatively low-cardinality keys.

Why Flat Tables Are Actually Okay

In a flat table, a lot more values are repeated. This sounds wasteful, but all those repeated customer names and product categories actually compress quite well via run-length encoding (if the sort order works out). The main downsides are that there are more columns to analyse for sort order (remember the 10-second budget), and scans over the flat table are bigger than scans over small dimension tables.

The best hour you can spend to refine your own data strategy and leverage the latest capabilities on Azure to accelerate your road map.

Why Header/Detail Is Usually Worst

The link between the two tables is an ID column - so with 100% cardinality, the biggest column is then repeated twice in the model. It gets almost no compression benefit. On top of that, every query traverses this high-cardinality relationship. As we discussed in the previous post: linking two large fact tables via their primary key is about the worst thing you can do.

Calculated Columns: Sometimes Helpful

Calculated columns have a bit of a bad reputation, and sometimes fairly. They increase model size and are computed during refresh. But there are cases where they can improve query performance.

Calculated columns can sometimes be a good idea, especially if the calculated column has lower cardinality than the columns it's derived from. For example, bucketing a high-precision decimal into ranges ("0-10", "10-20", etc.) creates a much lower-cardinality column that's faster to scan and filter.

But there really aren't any set rules here. Whether it helps depends on your data and queries - it always requires trying and testing.

Microsoft Fabric Weekly is a summary of the week's top news to help you build on the Microsoft Fabric Platform.

Testing Tips

A few practical things from the workshop:

Use real data for model testing. The distribution of values matters hugely for compression, so synthetic or sampled data can give misleading results.

Enable Server Timings in DAX Studio to see how long different operations take. Scanning different columns takes different amounts of time - if you do a SUM over a column with high cardinality, it will take noticeably longer. A direct consequence of the compression mechanics.

Measure, don't guess. Your intuition about which columns are problematic isn't always right. DAX Studio shows you what's actually happening.

What's Next

That wraps up the model optimisation half of the series. Look out for the next post on how the formula engine and storage engine work together when you actually execute a DAX query.

FAQs

Which model design is most efficient in Power BI? In most cases, star schemas produce the smallest and fastest models. Flat tables compress reasonably well due to repeated values. Header/detail designs tend to be the worst because the high-cardinality ID column linking the tables is stored in both, and every query pays an expensive relationship traversal cost.
When should I use calculated columns in Power BI? Calculated columns can improve performance when the result has lower cardinality than the inputs (e.g. bucketing values into ranges). But there are no hard rules - always measure the impact with DAX Studio rather than assuming.

Carmel Eve

Software Engineer II

Carmel Eve

Carmel is a software engineer and LinkedIn Learning instructor. She worked at endjin from 2016 to 2021, focused on delivering cloud-first solutions to a variety of problems. These included highly performant serverless architectures, web applications, reporting and insight pipelines, and data analytics engines. After a three-year career break spent travelling around the world, she rejoined endjin in 2024.

Carmel has written many blog posts covering a huge range of topics, including deconstructing Rx operators, agile estimation and planning and mental well-being and managing remote working.

Carmel has released two courses on LinkedIn Learning - one on the Az-204 exam (developing solutions for Microsoft Azure) and one on Azure Data Lake. She has also spoken at NDC, APISpecs, and SQLBits, covering a range of topics from reactive big-data processing to secure Azure architectures.

She is passionate about diversity and inclusivity in tech. She spent two years as a STEM ambassador in her local community and taking part in a local mentorship scheme. Through this work she hopes to be a part of positive change in the industry.

Carmel won "Apprentice Engineer of the Year" at the Computing Rising Star Awards 2019.