金年会-www.jinnianhui.com|金字招牌诚信至上

新闻活动

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

Power BI | 模型跑了两年突然报内存不足......

10/07/2026

01、模型跑了两年,早上突然挂了

周一早上8:47,小李的钉钉弹了三条消息。

第一条来自业务副总:「今天的销售日报怎么没推送?」第二条来自IT运维群:「Power BI Service刷新失败,报错:Resource Governing — not enough memory。」第三条是系统自动发的:「语义模型刷新已连续失败3次,当前状态:已禁用。」

小李打开Power BI Desktop,点刷新——转了两分钟,弹窗:内存不足,无法完成此操作。他看了一眼模型信息:1.8 GB。两年前上线时是420 MB。

数据量涨了不到一倍,模型体积涨了四倍多。问题究竟出在哪里?

别着急着花钱:在打开Azure Portal买更高SKU之前,先看看VertiPaq到底在你的模型里存了什么。

02、错误1:把数据源的每一列都拖进去了

小李用DAX Studio连上模型,跑了VertiPaq Analyzer。结果一出来,他自己都愣住了。前五大内存消耗列:

五列加起来占了模型体积的54%。而这些列,小李的报表里一列都没用到。

他当年从SQL Server导数据的时候,用的是 SELECT *。

这是一个几乎每个Power BI开发者都犯过的错。

源表有40列,你觉得万一以后用得上,全拉进来了。但Power BI不是SQL Server——它不存原始数据,它要把每一列压进VertiPaq的列式存储引擎。而这个引擎的效率,取决于一个东西:基数。

03、为什么高基数 = 内存灾难

VertiPaq对一列数据的压缩分四步:

  • 字典编码:把所有唯一值放进字典,数据只存索引。如果一列有100万行但只有3个唯一值(如「华东」「华南」「华北」),字典只有3条,压缩后几乎不占空间。
  • 值编码:如果是整数列且基数可控,直接用最少比特位存值,连字典都省了。
  • RLE(游程编码):连续相同值存成「值×次数」。排过序的列——比如日期——效果极好。
  • 哈希编码:如果前三步都搞不定(高基数、非整数),VertiPaq只能对每个值算哈希、建一个大字典。这是最差的编码方式,没有之一。

回到小李那五列:

OrderGUID:每行一个不同的GUID字符串。字典有多大?字典等于行数。字典编码彻底失效,RLE完全无效,只能哈希编码硬扛。370 MB,就这么来的。

CustomerNote:客服备注,自由文本。每行内容都不一样,但又不是数值,同样哈希编码伺候。

VertiPaq:精确到秒的时间戳。问题不在它是DateTime类型,而在它的精度。每行一个不同的秒级值 → 基数接近行数 → 字典爆炸。同等基数下,DateTime列比整数列多占近7倍内存——因为整数可以用值编码,DateTime不行。

VertiPaq不是被数据量打败的,是被「唯一值太多」打败的。10亿行只有3个产品的销售表,压缩比能做到20:1。100万行全是GUID的表,可能比10亿行还大。

04、错误2:把时间精度留给了报表层

小李的第二大问题是CreatedDateTime。业务上,销售报表只看到「天」——日趋势、周对比、月汇总。但源系统里存的是精确到秒的时间戳,他原封不动拉进来了。

处理方式极其简单:在Power Query里把CreatedDateTime拆成两列——OrderDate(Date类型)和OrderHour(整数,0-23)。

效果有多夸张?实测数据显示:一个DateTime列从秒级精度降到天级精度,该列占模型的比例从62%骤降到2.5%,整模型从约400 MB降到271 MB。

如果确实需要小时级分析,降到小时级就够了。

如果确实需要小时级分析,降到小时级就够了。

05、错误3:Auto Date/Time 悄悄吃掉20%内存

小李在 VertiPaq Analyzer 里还发现了一大堆他不认识的隐藏表——名字全是LocalDateTable_xxx。

这是Power BI的默认功能:自动日期/时间。每当你模型里有一个Date或DateTime列,Power BI就在后台悄悄给你建一张隐藏日期表。

小李的模型有7个日期列,7张隐藏表,合计占了约180 MB。

关掉它:

文件→选项和设置→选项→数据加载→取消勾选「自动日期/时间」。然后自己建一张显式日期维度表,一张就够了,所有事实表都关联它。

06、错误4:关系建在了字符串列上

小李的模型里,订单表和客户表通过 CustomerCode 关联。CustomerCode 是个VARCHAR(20) 的字符串列,形如 CUST-2023-SH-001587。

VertiPaq 分析显示,这一列的关系层次结构大小高达42 MB——因为关系索引里存的是字符串键,不是整数键。

修起来也简单:在数据源端给客户表加一列整数代理键CustomerKey,订单表同步加上,关系建在整数列上。字符串CustomerCode留在维度表里做展示用,但不再参与关系。

改完后关系索引从42 MB降到3 MB。整数键的字典编码效率远高于字符串键。

07、修完后的结果:1.8GB → 312MB

小李花了一个下午,做了五件事:

  • 从Power Query里删掉OrderGUID、CustomerNote、ProductImageURL、LastModifiedBy四列
  • 把CreatedDateTime拆成OrderDate(Date)和OrderHour(整数)
  • 关闭自动日期/时间,建了一张显式日期维度表;在数据源端加了整数代理键,关系改到整数列上
  • 把CreatedDateTime的另一个副本也一并处理掉

重新跑VertiPaq Analyzer:模型从1800 MB降到312 MB,压缩了83%。

刷新时间从6分半降到1分10秒。那三条钉钉消息,再也没出现过。他没有多花一分钱升级容量。

08、一套你可以照搬的排查流程

下次你的Power BI模型报内存不足,别急着加配置。按这四步走:

第一步:跑VertiPaq Analyzer
DAX Studio连上模型→Advanced→View Metrics。导出结果,按Total Size降序排列,找出前20大列。

第二步:标记三类「必杀」列
基数超过50万的列、字典大小超过10 MB的列、你没在任何一个报表视觉对象里用到的列。

第三步:逐列处理

  • 没用的列:直接在Power Query里删掉
  • 高精度DateTime:拆成Date+Hour
  • GUID/长字符串键:在数据源端换成整数代理键
  • 自由文本备注:如果不是分析对象就删掉。

第四步:验证
重新跑VertiPaq Analyzer,对比优化前后。压缩比低于5:1说明还有优化空间,做到10:1以上算优秀。

大多数人以为Power BI模型变大是因为数据太多了,其实很可能并不是。
模型变大,是因为唯一值太多了。VertiPaq不怕行数多,怕的是每一行都不一样。

下次从数据源拉数据时,先问自己两个问题:
「报表里真用得上吗?」、「这列的基数大概多少?」
这两个问题比任何优化技巧都管用。

Copyright © 2013-2026 深圳金年金字招牌诚信至上有限公司 粤ICP备14039318号

XML 地图