为何PowerBI合并两个文件的速度比Python慢两个数量级?
我有两个CSV文件:
- File A:270万行、5列、350MB
- File B:450万行、2列、185MB
我尝试基于单个列对它们做合并(join)操作。在我的机器上,用PowerBI加载CSV并完成合并需要20-25分钟;但用Python的Pandas DataFrame做同样操作只需要15-20秒。(相关查询语句和代码见下文)
我本来以为Python会比PowerBI快一点,但没想到差距是两个数量级。这些文件不算极小,但按数据分析标准也绝对算不上特别庞大。我觉得PowerBI默认设置下应该能处理这类常见的数据处理任务才对。
请问我是不是操作有误?有没有办法提升PowerBI的合并速度?或者PowerBI根本不适合这类任务?
PowerBI 查询语句
我通过三个PowerBI查询完成任务,前两个是点击New Source -> Text/CSV自动生成的,已禁用加载,仅用于第三个查询的合并。
FileA 查询
let Source = Csv.Document(File.Contents("path/to/a.csv"),[Delimiter=",", Columns=5, Encoding=1252, QuoteStyle=QuoteStyle.None]), #"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true]), #"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"ColA", type datetime}, {"ColB", type text}, {"ColC", type text}, {"ColD", type text}, {"ColE", type text}}) in #"Changed Type"
FileB 查询
let Source = Csv.Document(File.Contents("path/to/b.csv"),[Delimiter=",", Columns=2, Encoding=1252, QuoteStyle=QuoteStyle.None]), #"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true]), #"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"ColA", type text}, {"ColB", type datetime}}) in #"Changed Type"
Merge 查询
let Source = Table.NestedJoin(FileA, {"ColC"}, FileB, {"ColA"}, "FileB", JoinKind.LeftOuter), #"Expanded FileB" = Table.ExpandTableColumn(Source, "FileB", {"ColA", "ColB"}, {"FileB.ColA", "FileB.ColB"}) in #"Expanded FileB"
使用PowerBI Desktop版本:2.128.952.0 64位(2024年4月)
Python 代码
import pandas as pd # 加载数据框 with open("path/to/a.csv", "r") as file: df_a = pd.read_csv(file) with open("path/to/b.csv", "r") as file: df_b = pd.read_csv(file) # 合并数据框 df = pd.merge( df_a, df_b, how='left', left_on="ColC", right_on="ColA" )
使用Python 3.10.9及Pandas 1.5.3
1. 排查数据匹配的隐形问题
虽然你已将合并列设为text类型,但Power Query处理文本时可能保留空格、换行符等隐形格式差异,导致合并时采用效率极低的逐行全匹配而非哈希匹配。可以在两个文件的查询中添加文本清洗步骤:
在FileA的#"Changed Type"后添加:
#"Cleaned ColC" = Table.TransformColumns(#"Changed Type", {{"ColC", each Text.Clean(Text.Trim(_)), type text}})
在FileB的#"Changed Type"后添加:
#"Cleaned ColA" = Table.TransformColumns(#"Changed Type", {{"ColA", each Text.Clean(Text.Trim(_)), type text}})
2. 强制启用哈希合并算法
Power Query默认可能未开启哈希合并(大场景下效率远高于嵌套循环),修改Merge查询的Table.NestedJoin,手动指定算法:
Source = Table.NestedJoin(FileA, {"ColC"}, FileB, {"ColA"}, "FileB", JoinKind.LeftOuter, JoinAlgorithm.Hash)
3. 优化CSV加载效率
- 关闭自动类型检测:Power Query自动检测类型会额外消耗资源,你已手动指定类型,可在
Csv.Document参数中添加DetectTypes=false:Source = Csv.Document(File.Contents("path/to/a.csv"),[Delimiter=",", Columns=5, Encoding=1252, QuoteStyle=QuoteStyle.None, DetectTypes=false]) - 简化加载步骤:去掉不必要的中间转换,直接加载后再统一处理格式。
4. 调整PowerBI性能设置
- 确认64位加载已启用:在PowerBI选项的「数据加载」中勾选「启用64位数据加载」(你已用64位版本,需确认该开关打开)。
- 增加内存分配:在「选项」-「高级」中,根据机器内存(建议16G以上)调高「最大内存限制」。
- 关闭后台刷新:合并操作时暂停后台自动刷新,避免资源分流。
5. 关于PowerBI的适用场景
PowerBI核心定位是可视化与交互式分析,而非纯数据处理工具。对于大规模数据的合并、清洗,Pandas这类专门的数据分析库确实效率更高。但通过上述优化,PowerBI完全可以处理百万级别的数据合并;如果你的工作流后续需要做可视化,优化后的PowerBI能无缝衔接;如果只是纯数据处理,Python/Pandas会是更高效的选择。
内容的提问来源于stack exchange,提问作者Dacromir

