你有没有遇到过这种情况:在 Power BI 里跑一个 DAX 查询,数据量不大,存储引擎的事件看起来也一切正常,但查询就是慢——慢得莫名其妙。
打开 Server Timings 一看,第一个存储引擎查询迟迟不启动,查询开始和第一次取数之间有一段明显的空白。一旦数据开始读取,后面的过程又飞快。
问题不在数据,而在数据之前的那段等待。
这段等待叫公式引擎等待时间,而计算组(Calculation Groups)的某些使用模式,会让这段时间变得非常夸张。好消息是,Analysis Services 团队的工程师 Cory Laban 已经发布了修复补丁。
这篇文章不是产品公告,而是想讲清楚:那个间隙里引擎到底在干什么?为什么之前会这么慢?以及你怎么判断这个修复对你有没有用。
两个阶段:编译和执行
Cory 用了一个很形象的类比来解释 DAX 的执行过程。
如果把 DAX 看作一门编程语言,C 编译器会把 C 代码编译成汇编语言,然后 CPU 执行这些指令。数据库引擎也是一样——我们把人可读的 DAX 编译成存储引擎查询(相当于机器码),然后执行这些查询。
所以 DAX 查询分两个阶段:
- 编译阶段:包括 DAX 表达式的展开、静态分析和优化。这个阶段不读任何数据,你看到的那个“空白”就在这里。
- 执行阶段:真正跑存储引擎查询,读取实际数据。
问题出在编译阶段的“展开”
计算组之所以慢,是因为它在编译阶段需要做大量的表达式展开。
想象一下:你定义了一个计算组,里面有 10 个计算项,每个计算项又引用了不同的度量值。当你在查询里同时用到计算组和多个度量值时,引擎需要把每个组合都展开成独立的 DAX 表达式,然后逐一编译。
如果计算项里还嵌套了其他计算组,或者使用了复杂的上下文修改,展开的工作量会成倍增长。
更麻烦的是,这个展开过程是串行的——引擎必须等前一个表达式编译完,才能开始下一个。计算组越多、表达式越复杂,编译时间就越长。
修复了什么?
Cory 的修复核心是优化了计算组表达式的展开过程,减少了不必要的重复编译。
具体来说,旧版本中即使多个计算项共享相同的表达式片段,引擎也会重复编译。新版本会缓存这些公共片段,避免重复劳动。
用大白话说:以前是每次都要从头造轮子,现在学会了复用。
怎么判断修复对你有用?
升级到最新版本的 Power BI Desktop 或 Analysis Services 后,你可以用 Server Timings 对比一下:
- 运行一个包含计算组的查询,记录第一个存储引擎查询开始的时间。
- 升级前和升级后各跑一次,看这个时间差是否明显缩短。
如果你平时很少用计算组,或者查询里只用了简单的计算项,可能感觉不到差别。但如果你在复杂模型里大量使用计算组,尤其是嵌套计算组或多计算项组合,这个修复会带来显著的性能提升。
国内用户怎么看
说实话,计算组在国内 Power BI 用户中的普及程度还不算高,很多人在用计算组做动态切换度量值或时间智能的时候,遇到性能问题往往归咎于模型设计,很少有人意识到是编译阶段的锅。
这个修复对重度用户来说是个好消息,但更重要的是提醒我们:遇到性能问题,先看 Server Timings,别急着优化模型。
编译慢和查询慢是两回事,对症下药才能药到病除。
你用过计算组吗?遇到过编译慢的情况吗?欢迎在评论区分享你的经验。




