新闻活动

阅读公司最新动态、市场活动、媒体报道等最新公告。

Power BI | 为啥你的 Power BI 刷新巨慢?

23/07/2026

为啥你的 Power BI 刷新巨慢?

刷新慢,通常不是数据库慢,而是数据根本没在数据库里算。

小李负责的销售日报,每天早上 8:30 自动刷新。三个月前只要 40 秒,现在要 6 分 12 秒。

他先找 IT。IT 看了一眼服务器:

「SQL Server 资源使用率不到 15%,不是我们这边的问题。」

他再找 DBA。DBA 跑了一遍 SQL Profiler,截图发过来:

「你的 Power BI 在跑一条 SELECT * FROM SalesOrder,扫了全表 1200 万行。数据库不慢,是你每次刷新都在把整张表搬进 Power BI。」

小李打开 Power Query 编辑器,点开「销售订单」查询,数了一下:22 个应用步骤。筛选、去重、分组、合并、加自定义列、改数据类型,每一步他都觉得必须做。

问题不在数据库,也不在「22 步」这个数字本身,而在这些步骤最后变成了在哪里算。

一、查询折叠:把计算留在数据库里

Power Query 连接 SQL Server 这类关系型数据源时,有一个机制叫查询折叠。

简单说:你用 M 语言写的转换步骤——筛选行、选择列、分组聚合、排序——会被翻译成一条 SQL 语句发给数据库执行。数据库算完,只把结果返回给你。

情况 数据库实际执行的 传回 Power BI 的数据
折叠正常 带 WHERE、GROUP BY 的完整 SQL 筛选和汇总后的结果,例如 30 万行
折叠断开 SELECT * 或只带前几步条件的 SQL 全表 1200 万行,到本地再由 M 引擎逐条处理

折叠时,1200 万行先筛到 30 万行再传;折叠断了,1200 万行先进网卡、进内存,再被本地引擎一道道处理。

这 6 分钟不是算出来的,是搬出来的。

二、一个步骤就能毁掉整条折叠链

折叠的规则很硬:一旦某一步不可折叠,它后面的所有步骤——哪怕本身可以折叠——也一起失效。整条链从那个断点开始,全部在本地执行。

小李打开「查询折叠指示器」(Power Query 编辑器 → 视图 → 勾选「查询折叠指示器」),看到的顺序是:

步骤 折叠状态
导航(Navigation) 已折叠
删除其他列 已折叠
筛选:日期 ≥ 2026-01-01 已折叠
添加自定义列:Month = Date.Month([OrderDate]) 未折叠 · 断点
筛选:金额 > 1000 未折叠
分组汇总 未折叠
……后续所有步骤 全部未折叠

断点在第 4 步。Date.Month 在 SQL Server 端没有等价写法,折叠从这里断掉;后面的筛选、分组、去重,全部由 Power BI 在本地算完。

SQL Server 收到的实际查询是什么?DBA 截到的就是这一条:

SELECT * FROM [SalesOrder]
WHERE [OrderDate] >= '2026-01-01'

前 3 步折叠成了 WHERE 条件。第 4 步一断,第 5 步的「金额 > 1000」根本没进 SQL——它是数据全部被拉到本地之后才筛的。

三、三步修好:重排、替代、推到源

小李做了三件事,顺序不能颠倒:先让能折叠的步骤回到数据库,再处理那些确实折叠不了的。

01重排步骤:把能折叠的操作用到断点前面。

他原本的顺序是:

导航 → 删列 → 筛选日期 → 添加自定义列 → 筛选金额 → 分组

调整之后:

导航 → 删列 → 筛选日期 → 筛选金额 → 分组 → 添加自定义列

金额筛选和分组排到了自定义列前面,SQL Server 收到的查询变成:

SELECT [OrderDate], [Amount], [ProductID], [Region]
FROM [SalesOrder]
WHERE [OrderDate] >= '2026-01-01' AND [Amount] > 1000
GROUP BY [OrderDate], [ProductID], [Region]

数据库先筛再分组,返回的结果集只有 2 万行。自定义列在 2 万行上做,毫秒级。

02替换 M 函数:用可折叠的写法替掉不可折叠的。

他原来写 Date.Month([OrderDate]),是为了在报表里按月筛选。这个诉求完全可以在数据源端解决:

-- 在 SQL Server 建一个视图,把月份变成独立列
CREATE VIEW vw_SalesOrder AS
SELECT *, MONTH(OrderDate) AS OrderMonth
FROM SalesOrder

Power Query 直接连视图,OrderMonth 就是一个普通整数列,折叠不受影响。

03推到源:把复杂逻辑交给数据库。

另一步是 Table.AddColumn 里用一串嵌套 if 做客户分级。这在 Power Query 里不可折叠,但写成 SQL 的 CASE WHEN 完全没问题。他把这个字段也加进视图,Power Query 只负责拉现成数据。

修完再看折叠指示器:

步骤 折叠状态
导航(Navigation) 已折叠
删除其他列 已折叠
筛选:日期 ≥ 2026-01-01 已折叠
筛选:金额 > 1000 已折叠
分组汇总 已折叠
添加自定义列(字段来自视图) 已折叠

全绿。第二天早上 8:30,刷新用了 51 秒。

四、一个你可能每天都在犯的错

小李的问题不是技术不行,是他把 Power Query 当成了 ETL 工具。

Power Query 的定位是数据接入层:把数据从源系统接进来,做必要的列筛选和简单转换。它的设计目标是「把数据搬到模型里」,不是让你在 1200 万行上做字符串拼接、日期运算和嵌套条件判断。

一个粗略的判断标准:步骤超过 15 步,同时有 3 个以上自定义列,折叠大概率已经断了。

把复杂计算推回数据源。SQL 视图、存储过程,甚至直接在数据库里加计算列——任何能在数据源端完成的事,都比在 Power Query 里做强。

也不是所有步骤都能推到源,比如跨源合并、模糊匹配、调用外部接口。这类操作要放在折叠的最末端,并且先想办法把数据量压下来。

五、现在就查一下自己的模型

不用等下次刷新变慢,现在打开 Power BI Desktop,做三件事:

01打开折叠指示器。文件 → 选项和设置 → 选项 → Power Query 编辑器 → 勾选「查询折叠指示器」。然后打开 Power Query,看每个查询最后一步的图标颜色。

02找到第一个红色步骤。它就是断点。看它是什么操作——自定义列、日期函数、文本处理?把能折叠的步骤移到它前面。

03右键最后一步,看「查看原生查询」。灰色说明整条链都没折叠;可用就点开看 SQL 长什么样。如果只是一句不带 WHERE 的 SELECT *,说明你的筛选根本没进数据库。

三步走完还看不明白,就把这条 SQL 发给 DBA 对一下:数据库实际收到的,和你在 Power Query 里以为的,经常不是一回事。

写在最后

查询折叠不是优化技巧,而是 Power Query 连接关系型数据库的基本工作方式。折叠断了,等于你主动选择了「把所有数据拉到本地再算」。

这件事的代价不会一次爆发出来:数据量从 300 万涨到 1200 万,刷新就从 40 秒变成 6 分钟。等到有人开始抱怨日报出不来,问题往往已经存在很久了。

这句话值 6 分钟——报表每天早上多等的那 6 分钟。

想查清报表刷新慢在哪一步?
申请试用智能小V,做一次语义模型与刷新体检 →

Copyright © 2013-2026 深圳悦策科技有限公司 粤ICP备14039318号