我们有大数据集 - 几十个csv文件,每个〜130Gb。 我们必须在csv表上模拟sql查询。
当我们在测试1.1 Gb文件上使用encoding/csv
读取测试表时 - 程序分配526 Gb的虚拟内存。为什么?当我们使用csv.Reader
方法时,reader.Read()
就像生成器一样工作,或者它在内存中保留行?
在code后完整codereview。
UPD
读取文件如:
rf, err := os.Open(input_file)
if err != nil {
log.Fatal("Error: %s", err)
}
r := csv.NewReader(rf)
for {
record, err := r.Read()
}
因内存错误而落在record, err := r.Read()
行。
UPD2 读取过程中的内存快照:
2731.44MB 94.63% 94.63% 2731.44MB 94.63% encoding/csv.(*Reader).parseRecord
151MB 5.23% 99.86% 2885.96MB 100% main.main
0 0% 99.86% 2731.44MB 94.63% encoding/csv.(*Reader).Read
0 0% 99.86% 2886.49MB 100% runtime.goexit
0 0% 99.86% 2886.49MB 100% runtime.main
答案 0 :(得分:4)
很可能没有检测到换行符并将其作为单个记录读取。
https://golang.org/src/encoding/csv/reader.go?s=4071:4123#L124
如果您按照第210行的代码操作,则会看到它查找'\n'
。
当某些系统将其导出时,我经常看到换行符定义为\n\r
,认为它们实际上是Windows智能的,实际上它是错误的。正确的Windows换行符为\r\n
。
或者,您可以编写一个自定义Scanner
,使用输入中的任何技术为您排除线条,并将其用作io.Reader
的{{1}}输入。例如,要使用上面提到的无效csv.Reader
。