繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM