我有很大的制表符分隔文件(10GB-70GB),需要进行一些读取,数据操作和写入单独的文件。这些文件的范围可以是100到10K列,行数为200万到500万。
前x列是静态的,是参考所需的。样本文件格式:
HTMLElement.prototype.on = function(event, selector, handler) {
this.addEventListener(event, function(e) {
let target = e.target;
if (typeof(selector) === 'string') {
while (!target.matches(selector) && target !== this) {
target = target.parentElement;
}
if (target.matches(selector))
handler.call(target, e);
} else {
selector.call(this, e);
}
});
};
我需要使用前两列来获取产品ID,然后生成类似于:
的输出文件#ProductName Brand Customer1 Customer2 Customer3
Corolla Toyota Y N Y
Accord Honda Y Y N
Civic Honda 0 1 1
当前示例代码:
ProductID1 Customer1 Y
ProductID1 Customer2 N
ProductID1 Customer3 Y
ProductID2 Customer1 Y
ProductID2 Customer2 Y
ProductID2 Customer3 N
ProductID3 Customer1 N
ProductID3 Customer2 Y
ProductID3 Customer3 Y
我运行的一项测试花了大约12个小时来读取一个包含300万行和2500列的文件(70GB)。最终输出文件生成250GB,大约有8亿多行。
我的问题是:除了我已经做过的可以提供更快性能的Scala之外还有什么内容吗?
答案 0 :(得分:1)
好的,有些想法......
flush
。所以,是的,摆脱它。PrintWriter
默认情况下会在每个换行符后刷新(因此,目前,您实际上正在刷新两次:))。在创建PrintWriter
时使用双参数构造函数,并确保第二个参数为false BufferedWriter
,PrintWriter
默认情况下已经缓存。默认的缓冲区大小是8K,您可能想尝试使用它,但它可能没有任何区别,因为,最后我检查,基础FileOutputStream
忽略所有这些,并刷新千字节大小的块无论哪种方式。 GZipOutputStream
。这不仅可以减少实际访问磁盘的物理数据量,还可以实现更大的缓冲区parser
内容正在做什么。你没有显示实现,但有些东西告诉我它可能不是免费的。split
在巨大的字符串上会变得非常昂贵。人们常常忘记,它的参数实际上是一个正则表达式。你可能最好不要编写自定义迭代器,或者只是使用古老的StringTokenizer
来解析字段,而不是预先分割。至少,它可以为每行节省一次额外的扫描。最后,最后,但绝不是最不重要的。 考虑使用spark和hdfs 。这类问题是这些工具真正擅长的领域。