PowerShell优化:快速从25万行CSV提取指定Campaign Ref Code并导出
优化大CSV文件的分流处理脚本
原脚本的核心问题是重复读取源CSV文件——3组Ref列表,每组循环10次,总共要读30次25万行的文件,IO开销拉满,这就是耗时超1小时的根本原因。
优化思路
- 只读取一次源CSV到内存,彻底减少IO操作
- 用哈希表建立「Ref Code → 输出文件」的映射,实现O(1)的快速匹配
- 遍历内存中的数据,一次完成所有分流
优化后的脚本(基础版)
$sourceFile = 'Orig.csv' $workDir = '.' # 替换成你的实际工作目录 $today = Get-Date -Format 'yyyyMMdd' # 建立Ref Code到输出文件的映射表 $refToFile = @{ # File1对应的Refs 'COLMABQ140' = "File1.$today.csv" 'COLMABQ141' = "File1.$today.csv" 'COLMABQ142' = "File1.$today.csv" 'COLMABQ143' = "File1.$today.csv" 'COLMABQ144' = "File1.$today.csv" 'COLMABQ176' = "File1.$today.csv" 'COLMABQ177' = "File1.$today.csv" 'COLMABQ178' = "File1.$today.csv" 'COLMABQ179' = "File1.$today.csv" 'COLMABQ180' = "File1.$today.csv" # File2对应的Refs 'COLMABP140' = "File2.$today.csv" 'COLMABP141' = "File2.$today.csv" 'COLMABP142' = "File2.$today.csv" 'COLMABP143' = "File2.$today.csv" 'COLMABP144' = "File2.$today.csv" 'COLMABP176' = "File2.$today.csv" 'COLMABP177' = "File2.$today.csv" 'COLMABP178' = "File2.$today.csv" 'COLMABP179' = "File2.$today.csv" 'COLMABP180' = "File2.$today.csv" # File3对应的Refs 'COLMABS140' = "File3.$today.csv" 'COLMABS141' = "File3.$today.csv" 'COLMABS142' = "File3.$today.csv" 'COLMABS143' = "File3.$today.csv" 'COLMABS144' = "File3.$today.csv" 'COLMABS176' = "File3.$today.csv" 'COLMABS177' = "File3.$today.csv" 'COLMABS178' = "File3.$today.csv" 'COLMABS179' = "File3.$today.csv" 'COLMABS180' = "File3.$today.csv" } # 一次性读取源CSV到内存 $csvData = Import-Csv -Path $sourceFile # 初始化每个输出文件,先写入表头(避免重复写入) $outputFiles = $refToFile.Values | Select-Object -Unique foreach ($outFile in $outputFiles) { $csvData[0] | Export-Csv -Path (Join-Path $workDir $outFile) -NoTypeInformation -Force } # 遍历数据行,根据Ref Code分流到对应文件 foreach ($row in $csvData) { $refCode = $row.'Campaign Ref Code' if ($refToFile.ContainsKey($refCode)) { $outPath = Join-Path $workDir $refToFile[$refCode] $row | Export-Csv -Path $outPath -NoTypeInformation -Append } }
进阶优化版(减少磁盘写入次数)
如果想进一步提速,可以把同一文件的行先收集到数组里,最后一次性导出,减少磁盘写入的零散开销:
$sourceFile = 'Orig.csv' $workDir = '.' $today = Get-Date -Format 'yyyyMMdd' $refToFile = @{ # 同上的映射表内容... } # 初始化每个文件的行集合 $fileRows = @{} $outputFiles = $refToFile.Values | Select-Object -Unique foreach ($file in $outputFiles) { $fileRows[$file] = @() } # 一次性读取源数据 $csvData = Import-Csv -Path $sourceFile # 收集对应文件的行 foreach ($row in $csvData) { $refCode = $row.'Campaign Ref Code' if ($refToFile.ContainsKey($refCode)) { $targetFile = $refToFile[$refCode] $fileRows[$targetFile] += $row } } # 批量导出每个文件 foreach ($file in $fileRows.Keys) { if ($fileRows[$file].Count -gt 0) { $fileRows[$file] | Export-Csv -Path (Join-Path $workDir $file) -NoTypeInformation -Force } }
性能提升原因
- 只做一次源文件读取,避免了30次重复IO操作(这是最大的性能瓶颈)
- 哈希表匹配是O(1)时间复杂度,比原脚本每次循环的
Where-Object快得多 - 进阶版把多次
Append写入改成一次性批量导出,进一步降低磁盘IO的开销
实测下来,这种处理方式能把耗时压缩到几分钟甚至更短,具体取决于你的硬件性能。
内容的提问来源于stack exchange,提问作者DarrenB
相关产品推荐
相关产品推荐

