(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisbon
Modelação de Dados (Kimball)
Modelação de Dados (Kimball) 2 min

Modeling for Power BI: optimize the semantic model with VertiPaq

João Barros 06 de January de 2026 2 min read

The VertiPaq engine in Power BI (and Analysis Services) has storage and execution characteristics different from a traditional RDBMS. Modeling specifically for VertiPaq can improve query performance by 10x or more.

How VertiPaq stores data

VertiPaq = columnar + dictionary compression
  - Each column stored separately
  - Dictionary: unique values → compact integer IDs
  - Run-length encoding for consecutive repeated values
  - Impact: columns with FEW unique values compress better
  - 1 TEXT column "Country" with 50 unique values ≈ 3-4 bytes/row
  - 1 TEXT column "Description" with 1M unique values ≈ 50+ bytes/row

Golden rules for VertiPaq

1. REMOVE columns not used in visuals or relationships
   → Each column takes memory EVEN without relationships

2. AVOID unnecessary high-cardinality columns
   → Fields like "free comment" or "sequential ID with prefix"
   → Prefer integers (ID INT) to strings ('PROD-001234')

3. NEVER use RELATED() in calculated columns on fact tables
   → Materializes the column on every row — blows up the model

4. USE measures instead of calculated columns for aggregations
   → Measures compute at query time; calculated columns take memory

5. DATES as Date type (not DateTime) when you don't need time
   → DateTime has much higher cardinality

Diagnose with DAX Studio

-- See the size of each model column
EVALUATE
SELECTCOLUMNS(
    FILTER(
        INFO.STORAGETABLECOLUMNS(),
        [DICTIONARY_SIZE_KB] > 100
    ),
    "Table",       [DIMENSION_NAME],
    "Column",      [ATTRIBUTE_NAME],
    "Dict KB",     [DICTIONARY_SIZE_KB],
    "Data KB",     [USED_SIZE_KB],
    "Cardinality", [SEGMENT_COUNT]
)
ORDER BY [DICTIONARY_SIZE_KB] DESC

Relationships and filtering

-- Rules for Power BI relationships:
✓ Whenever possible: 1:N relationship (dimension → facts)
✗ Avoid: direct many-to-many
✗ Avoid: bidirectional filtering (Both)
   → Causes ambiguous queries and filter loops
   → Use the DAX CROSSFILTER() function only when absolutely necessary

Conclusion

Optimizing for VertiPaq is not about SQL — it is about cardinality, number of columns and measure design. A well-optimized model fits in 10x less memory, loads in half the time and answers queries 5-10x faster. Invest 30 minutes in DAX Studio after each model refresh.

Share: