[英]Speeding up a pattern matching algorithm in scala on a big csv file
我目前正在尝试使用Scala过滤大型数据库。 我编写了一段简单的代码,将一个数据库中的ID与另一个数据库中的ID列表进行匹配。
本质上,我想浏览数据库A,如果ID列中的ID号与数据库B中的ID匹配,则从数据库A中提取该条目。
我编写的代码可以正常工作,但是速度很慢(即必须运行几天),并且我正在尝试找到一种加快速度的方法。 可能是它不能加速太多,或者通过更好的编码它可以快得多。
因此,任何帮助将不胜感激。
下面是数据库的描述和代码的副本。
数据库A的大小约为10gb,具有超过1亿个条目,数据库B的列表包含约50,000个ID。
每个数据库如下所示:
Database A:
ID, DataX, date
10, 100,01012000
15, 20, 01012008
5, 32, 01012006
etc...
Database B:
ID
10
15
12
etc...
我的代码如下:
import scala.io.Source
import java.io._
object filter extends App {
def ext[T <: Closeable, R](resource: T)(block: T => R): R = {
try { block(resource) }
finally { resource.close() }
}
val key = io.Source.fromFile("C:\\~Database_B.csv").getLines()
val key2 = new Array[String](50000)
key.copyToArray(key2)
ext(new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\~Output.csv")))) {
writer =>
val line = io.Source.fromFile("C:\\~Database_A.csv").getLines.drop(1)
while (line.hasNext) {
val data= line.next
val array = data.split(",").map(_.trim)
val idA = array(0)
val dataX = array(1)
val date = array(2)
key2.map { idB =>
if (idA == idB) {
val print = (idA + "," + dataX + "," + date)
writer.write(print)
writer.newLine()
} else None
}
}
}
}
首先,有比编写Scala程序更有效的方法。 在现代计算机上,将两个表加载到数据库中并进行联接将花费大约10分钟(包括数据加载)。
假设您必须使用Scala,会有明显的改进。 将密钥存储为HashSet并使用keys.contains(x)
而不是遍历所有密钥。 这将为您提供O(1)查找,而不是现在的O(N)查找,这将显着提高程序速度。
次要点-使用字符串插值代替串联,即
s"$idA,$dataX,$date"
// instead of
idA + "," + dataX + "," + date
尝试这个:
import scala.io.Source
import java.io._
object filter extends App {
def ext[T <: Closeable, R](resource: T)(block: T => R): R = {
try { block(resource) }
finally { resource.close() }
}
// convert to a Set
val key2 = io.Source.fromFile("C:\\~Database_B.csv").getLines().toSet
ext(new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\~Output.csv")))) {
writer =>
val lines = io.Source.fromFile("C:\\~Database_A.csv").getLines.drop(1)
for (data <- lines) {
val array = data.split(",").map(_.trim)
array match {
case Array(idA, dataX, date) =>
if (key2.contains(idA)) {
val print = (idA + "," + dataX + "," + date)
writer.write(print)
writer.newLine()
}
case _ => // invalid input
}
}
}
}
现在将ID存储在集中。 这样可以提供更好的性能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.