我目前正在尝试使用scala过滤大型数据库。我编写了一段简单的代码,将一个数据库中的ID与另一个数据库中的ID列表进行匹配。
基本上我想通过数据库A,如果ID列中的ID号与数据库B中的ID号匹配,则从数据库A中提取该条目。
我写的代码工作正常,但速度很慢(即必须运行几天),我正试图找到加快速度的方法。它可能不会被加速,或者通过更好的编码可以快得多。
所以任何帮助都会非常感激。
以下是数据库的说明和代码的副本。
数据库A的大小约为10GB,条目数超过1亿,数据库B的列表大约有50,000个。
每个数据库如下所示:
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
}
}
}
}
答案 0 :(得分:3)
首先,有一种比编写Scala程序更有效的方法。在数据库中加载两个表并进行连接将在现代计算机上花费大约10分钟(包括数据加载)。
假设您必须使用scala,则有明显的改进。将密钥存储为HashSet并使用keys.contains(x)
而不是遍历所有密钥。这将为您提供O(1)查找而不是现在的O(N),这将显着加快您的程序。
次要点 - 使用字符串插值而不是连接,即
s"$idA,$dataX,$date"
// instead of
idA + "," + dataX + "," + date
答案 1 :(得分:1)
试试这个:
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现在存储在一个集合中。这样可以提供更好的性能。