ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 615|回复: 10

[求助] PowerQuery加载到Sheet页中速度很慢

[复制链接]

TA的精华主题

TA的得分主题

发表于 2024-9-20 18:10 | 显示全部楼层 |阅读模式
本帖最后由 碧色之雨 于 2024-9-20 18:14 编辑

与这篇贴子的情况类似,但是看原贴最后也没有找到解决办法Power query加载至表,非常慢-Power BI-ExcelHome技术论坛 -

我的数据量大概在20w条左右,在pq编辑器里进行全部刷新大约需要1-2分钟就能完成,但是一加载到Excel的Sheet页中,就变得非常慢,每秒只能加载10几行。

经过逐行检查加载速度,发现在执行一个Table.ExpandTableColumn语句后,加载速度明显下降。查了好几天的资料也没找到原因,尝试不用ExpandTableColumn展开,而是通过AddCloumn添加新列时对含嵌套表的列进行深化取数,但是不能解决该问题。
有没有大佬能帮帮忙看看有什么解决办法。
以下是源码
  1. let
  2.     缓存备案台账 = Table.Buffer(备案台账),
  3.     缓存解保台账 = Table.Buffer(解保台账),
  4.     缓存银行名称映射 = Table.Buffer(银行名称映射),
  5.     缓存再担保费率表 = Table.Buffer(再担保费率表),

  6.     小微标识 = Table.AddColumn(缓存备案台账, "辅_小微标识", each if [债务人类别]="个体工商户" or [债务人类别]="小微企业主" or [企业划型]="小型企业" or [企业划型]="微型企业" then 1 else 0, Int8.Type),
  7.     三农标识 = Table.AddColumn(小微标识,"辅_三农标识", each if [债务人类别]="农户" or [行业_工标]="农、林、牧、渔业" then 1 else 0, Int8.Type),
  8.     小微或三农 = Table.AddColumn(三农标识,"辅_小微或三农", each if [辅_小微标识]=1 or [辅_三农标识]=1 then 1 else 0, Int8.Type),
  9.     银行名称 = Table.AddColumn(小微或三农, "辅_匹配银行", (x)=>(
  10.         let
  11.             下标 = List.PositionOf(List.Transform(缓存银行名称映射[原名称], (y)=> if Text.Contains(x[债权人名称],y)=true then 1 else 0),1)
  12.         in
  13.             if 下标 = -1 then "未匹配到银行" else 缓存银行名称映射[标准名称]{下标}
  14.     ), Text.Type),
  15.     业务大类 = Table.AddColumn(银行名称, "辅_业务大类", (x)=>(
  16.         if Text.Start(x[省再产品],7)="国担备案财园通" then "国担财园通"
  17.         else if Text.Start(x[省再产品],4)="省内单独" then "省内单独备案财园通"
  18.         else if List.Max(List.Transform(国担总对总产品列表, (y)=>if Text.Contains(x[省再产品],y) then 1 else 0))=1 then "国担总对总"
  19.         else "常规业务"
  20.     ),Text.Type),
  21.    
  22.     责任比例 = Table.AddColumn(业务大类, "辅_责任比例", each
  23.         ((if ([省再确认时间]<=统计日期) and (not([省再确认时间] is null)) then [分险比例_省级再担保] else 0) +
  24.         (if [辅_业务大类]="国担总对总" then 0 else [分险比例_国担]))/100
  25.     , Number.Type),

  26.     再担保费率 = Table.AddColumn(责任比例, "辅_再担保费率", (x)=>Table.SelectRows(缓存再担保费率表, (y)=>(y[业务类型]=x[辅_业务大类]) and (y[起始日期]<=List.Max({Date.FromText("2000/1/1"),x[国担确认时间]})) and (y[结束日期]>=List.Max({Date.FromText("2000/1/1"),x[国担确认时间]})) and (y[金额下限]<(if x[主债权金额] is null then 0 else x[主债权金额])) and (y[金额上限]>=(if x[主债权金额] is null then 0 else x[主债权金额])))[费率]{0}, Number.Type),
  27.     户数统计 = Table.AddColumn(再担保费率, "辅_户数统计", each [直担机构名称]&"_"&[债务人名称], Text.Type),
  28.     私营标识 = Table.AddColumn(户数统计, "辅_私营标识", each if [债务人经济成分] is null or Text.Start([债务人经济成分],1)="私" or Text.Start([债务人经济成分],3)="自然人" then 1 else 0, Int8.Type),
  29.     合并的查询 = Table.NestedJoin(私营标识, {"唯一业务编号"}, 缓存解保台账, {"业务编号"}, "再担保解保台账", JoinKind.LeftOuter),
  30.     添加解保日期 = Table.AddColumn(合并的查询,"辅_自动解保日期", each List.Max({[主债权到期日期],[省再确认时间]})),
  31.     添加解保金额 = Table.ExpandTableColumn(添加解保日期, "再担保解保台账", {"年初解保金额","本年解保金额"}, {"临_年初解保金额","临_本年解保金额"}),
  32.     修正解保金额空值 = Table.ReplaceValue(添加解保金额, null, 0, Replacer.ReplaceValue, {"临_年初解保金额","临_本年解保金额"}),
  33.     年初贷款 = Table.AddColumn(修正解保金额空值,"辅_年初贷款金额", each if [辅_自动解保日期]<年初日期 or [省再确认时间]>=年初日期 then 0 else [主债权金额]-[临_年初解保金额], Currency.Type),
  34.     本年新增贷款 = Table.AddColumn(年初贷款, "辅_本年新增贷款金额", each if [省再确认时间]>=年初日期 and [省再确认时间]<=统计日期 then [主债权金额] else 0, Currency.Type),
  35.     本年解保贷款 = Table.AddColumn(本年新增贷款, "辅_本年解保贷款金额", each if [辅_自动解保日期]>=年初日期 and [辅_自动解保日期]<=统计日期 then [辅_年初贷款金额]+[辅_本年新增贷款金额] else [临_本年解保金额], Currency.Type),
  36.     期末贷款 = Table.AddColumn(本年解保贷款,"辅_期末贷款金额", each [辅_年初贷款金额]+[辅_本年新增贷款金额]-[辅_本年解保贷款金额], Currency.Type),
  37.     年初担保 = Table.AddColumn(期末贷款, "辅_年初担保金额", each [辅_年初贷款金额]*[辅_责任比例], Currency.Type),
  38.     本年新增担保 = Table.AddColumn(年初担保, "辅_本年新增担保金额", each [辅_本年新增贷款金额]*[辅_责任比例], Currency.Type),
  39.     本年解保担保 = Table.AddColumn(本年新增担保, "辅_本年解保担保金额", each [辅_本年解保贷款金额]*[辅_责任比例], Currency.Type),
  40.     期末担保 = Table.AddColumn(本年解保担保, "辅_期末担保金额", each [辅_期末贷款金额]*[辅_责任比例], Currency.Type),
  41.     删除临时字段 = Table.RemoveColumns(期末担保, {"临_年初解保金额","临_本年解保金额"}),
  42. in
  43.     删除临时字段
复制代码



再担保.zip

36.34 KB, 下载次数: 3

TA的精华主题

TA的得分主题

发表于 2024-9-20 21:56 | 显示全部楼层
你这个很难优化,叉乘的复杂度有点多,比如12行,19行,28行,31行,33行都是很费时间的。再一个,最终结果的列数有没有大于30列,明显是一个宽表,20万行30多列,占用内存大概3G左右,正常加载出去1分钟左右应该是合理的。前两步备案台账和解保台账不需缓存,意义不大。31行和33行似乎跟前边30步没有关联,把这两步挪到一开始去做,再一列一列添加字段,看看会不会好一些。算法上没有改进空间,写法上看能不能减少点时间。没有数据,不好测试,仅供参考。

TA的精华主题

TA的得分主题

发表于 2024-9-20 23:09 | 显示全部楼层
你发的文件没有数据源,没法测试.一些添加列的步骤可以试试改成recoed的方式来写,辅助过渡的后面也就不需要展开了.

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-9-22 19:56 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
飞天篮球猪 发表于 2024-9-20 21:56
你这个很难优化,叉乘的复杂度有点多,比如12行,19行,28行,31行,33行都是很费时间的。再一个,最终结果 ...

谢谢大佬回复。有几个问题想跟您探讨一下,首先前面几行的缓存是因为buffer的两张表本身也是引用了外部数据的查询,我之前发现不buffer一下的话,本查询在计算过程中会反复引用源文件(猜测是执行某些循环的时候),导致计算时间特别长,查了微软的文档才发现有buffer这个函数,试了一下,效果不错。
业务本身场景确实比较复杂,用pq的目的其实就是为了给原始台账添加一系列的辅助列,方便后续的各种统计。原本用函数的,但是数据量起来了以后函数的效率就很低了。
我现在的痛点就是在pq编辑器里刷新这张表的时间是正常的,1分多钟,唯独加载到Sheet的时间特别长,查了很多资料也没有可靠的解决办法,所以来这求助。

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-9-22 19:59 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
jiffy92010 发表于 2024-9-20 23:09
你发的文件没有数据源,没法测试.一些添加列的步骤可以试试改成recoed的方式来写,辅助过渡的后面也就不需要 ...

因为数据源特别大,好几张上百MB的Excel。
您后面说的我有点没太看懂。是说将Table转成record么?这样可以提高效率吗?我只学习pq一个月左右,还没怎么仔细研究过这种写法。
不过我现在的问题还是加载到Excel的sheet表里有困难,不清楚为什么在pq编辑器里刷新很快,但是加载到表就很花时间,也没查阅到相关的资料

TA的精华主题

TA的得分主题

发表于 2024-9-22 20:12 | 显示全部楼层
编辑器里是惰性计算,刷新1分钟属于很慢了,等加载出去的时候就会更慢。
你这样数据量的实务应用已经不适合PQ了,浪费时间,换成其它工具吧。
笛卡尔积,也就是叉乘的复杂度,还有一个关联查询,PQ无论如何是快不起来的。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-9-23 10:03 | 显示全部楼层
飞天篮球猪 发表于 2024-9-22 20:12
编辑器里是惰性计算,刷新1分钟属于很慢了,等加载出去的时候就会更慢。
你这样数据量的实务应用已经不适 ...

原来是这样,看来我还是得学习一下新的工具。本来以为几十万的数据量还是可以用pq的。谢谢大佬指教!

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-9-23 10:15 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
飞天篮球猪 发表于 2024-9-22 20:12
编辑器里是惰性计算,刷新1分钟属于很慢了,等加载出去的时候就会更慢。
你这样数据量的实务应用已经不适 ...

大佬我想再请教一个问题,我在调试代码的过程中,发现造成性能明显下降的代码就是第33行的展开列。到第32行的时候,感觉都是正常的,加载速度大概每秒3000多行,一旦把33行代码加上,性能立刻掉到每秒10几行。从我直观上理解,我觉得ExpandTableColumn并不是什么计算量很大的步骤,您知道这是什么原因么?

TA的精华主题

TA的得分主题

发表于 2024-9-23 11:15 | 显示全部楼层
碧色之雨 发表于 2024-9-23 10:03
原来是这样,看来我还是得学习一下新的工具。本来以为几十万的数据量还是可以用pq的。谢谢大佬指教!

说3毛钱想法:

1、上百兆的EXCEL文件,其实已经不适合用EXCEL作为存储媒介了,EXCEL存储时除了纯数据还有很多其他的东西,后续用工具去读excel文件会很慢。同样的文件,你可以去比较一下用Excel存储和用csv/txt存储,文件读写哪个快,更不用说用数据库或者一些特定格式的行存、列存文件,所以想一下换一种存储方式;

2、PQ作为混合数据源mashup计算,他的算力是不够的,计算也不是他的活,如果数据源比较规范,不需要复杂的清洗和计算,那几十万行是没有问题的。PQ适合把多种类型的数据源合并在一起,比如从数据库,文本文件,网页等等取数,然后简单的清洗,这是他的活,后续复杂的计算交给其它工具,比如pbi配套的DAX,这个列式引擎才是用于计算的。所以,想想换一个工具。

3、你当前的案例,因为算法上不能优化,可能换了工具也不见得会有很理想的提速效果,如果工具的底层算法优化的好,效果也会好,总体只要能保证跑出结果,系统不崩溃就可以了。

仅供参考。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2024-9-23 11:18 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
碧色之雨 发表于 2024-9-23 10:15
大佬我想再请教一个问题,我在调试代码的过程中,发现造成性能明显下降的代码就是第33行的展开列。到第32 ...

原因还真的不清楚,但一直以来都是不推荐使用expand这个步骤的,所有带有expand的都不推荐,不要为了图方便。你想想,看能不能用其它方法替代这个步骤。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-12-4 01:21 , Processed in 0.051474 second(s), 13 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表