在大型csv文件中加快scala中的模式匹配算法

时间:2015-09-03 16:09:23

标签: database performance scala csv

我目前正在尝试使用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
    }
  }
}

}

2 个答案:

答案 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现在存储在一个集合中。这样可以提供更好的性能。

相关问题