PBI DAX Performance
SkillFiles & storageUse when a DAX query, measure, or visual is slow, when interpreting analyze timings, Storage Engine / Formula Engine splits, or query plans, when VertiPaq storage size or cardinality drives cost, or when the user wants a tuning pass or before/after benchmark. For wrong values, use mcp-engine-dax-debugging; for writing new queries, use mcp-engine-query; for a whole-model assessment, use mcp-engine-model-quality.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the PBI DAX Performance skill
What this skill tells your AI
The instructions your AI receives, as published by maxanatsko/mcp-engine-public in skills/mcp-engine-dax-performance/SKILL.md and read by ahel’s review.
Optimization of correct-but-slow queries: measure, change one thing, re-measure. Never claim a speedup without an identical before/after comparison.
Optimization loop
- Baseline —
run_query{ "operation": "analyze", "query": "<slow query>", "spec": { "runs": 5, "clear_cache": true } }. On Desktop, call this cold-cache only when the response has noclear_cache failedlimitation; otherwise fix cache clearing or start a separate warm-cache run withclear_cache: false, discard run 1, and use the median of runs 2–5. On Service XMLA, cache clearing is unavailable: record that limitation, discard run 1 as warm-up, and use the median of runs 2–5 as the warm-cache baseline. The Service Storage Engine / Formula Engine split comes from discarded run 1, so use it only as diagnostic triage, not as baseline or before/after evidence. Record run variance. For very fast queries (<10ms) increaseruns— noise dominates. - Triage — classify with performance-remediation-playbook section A: SE-heavy, FE-heavy, or model-size pressure. Interpretation rules for timings live in query-performance-guide.
- Capture the plan when operators matter — add
"include_query_plan": trueto spec (Pro); decode unfamiliar operators with dax-query-plan-reference. - Check storage when SE-heavy or memory-bound —
run_query{ "operation": "vertipaq", "spec": { "table": "<table>", "include_cardinality": true } }; remediation options in vertipaq-optimization-guide. - Hypothesize and change one thing — the playbook's symptom table maps each diagnosis to its fix. Route the edit: measure rewrite →
mcp-engine-semantic-authoring; model shape, columns, or relationships →mcp-engine-schema-authoring(ormcp-engine-refactoringwhen consumers are involved). If a named skill is not installed, make the edit from the tool'sinputSchemaand the model's conventions, or ask the user to add that skill. - Re-measure identically — same query text, connection kind,
runs, and cache treatment. On Service XMLA, again discard run 1 and compare the median of the remaining identical warm runs. Keep the change only when the comparison shows it; revert otherwise and try the next hypothesis. - Protect the win — pin the result with a connection-appropriate
performance_budgetdefinition. On Desktop with verified cache clearing, validatemanage_tests{ "operation": "validate", "spec": { "id": "<test-id>", "name": "<name>", "type": "performance_budget", "spec": { "query": "<tuned query>", "runs": { "cold": 1, "warm": 3 } }, "assert": { "kind": "performance", "total_ms": { "max": <cold-and-warm-budget> } } } }. On Service XMLA, validate{ "operation": "validate", "spec": { "id": "<test-id>", "name": "<name>", "type": "performance_budget", "spec": { "query": "<tuned query>", "runs": { "cold": 1, "warm": 3 } }, "assert": { "kind": "performance", "warm_ms": { "max": <warm-budget> } } } }: the unsupportedcoldslot is the unasserted warm-up, whilewarm_ms.maxcovers only the following three runner timings. Derive the Service threshold from the maximum post-warm-up timing plus approved headroom, not from the discarded first run or the analyze median. Then call{ "operation": "put" }with the same completespec, followed by{ "operation": "run" }so regressions surface in test runs. Never apply a Desktoptotal_msbudget to Service results.
Guardrails
- One change per iteration; a two-change iteration cannot attribute its result.
- On Desktop, use
clear_cache: truewhen comparing alternatives and verify it succeeded; if not, resolve the failure or start a new run withclear_cache: false, discard run 1, and compare the remaining warm samples. On Service XMLA, state that cache clearing is unavailable and discard run 1 before comparing warm samples. Never mix successful and failed cache-clear attempts or label unavailable clearing as cold-cache results. - Optimize the model shape before micro-optimizing DAX when the playbook triage points at structure.
- Plans and traces can be large: summarize findings, do not paste raw dumps to the user.
Report results
After a tuning pass, report:
- The query tuned and the baseline numbers (total, SE/FE split, runs).
- Each hypothesis tried, the change made, and its measured effect.
- The final before/after comparison for kept changes.
- Changes reverted and why.
- The
performance_budgettest added, with its id.
References
- query-performance-guide — analyze usage, timing interpretation, run statistics
- dax-query-plan-reference — plan operator definitions
- vertipaq-optimization-guide — storage footprint and cardinality remediation
- performance-remediation-playbook — triage, symptom-to-fix table, golden baseline queries
Signals
- GitHub stars
- 256
- Forks
- 65
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
mcp-engine-dax-performance- Source
- github.com/maxanatsko/mcp-engine-public