scala—如何最好地读取文件并转换为spark sqlcontext数据集

oyjwcjzk  于 2021-05-27  发布在  Spark
关注(0)|答案(2)|浏览(296)

我想读取一个没有标题的制表符分隔的文件(示例行如下)

196 242 3   881250949
186 302 3   891717742

我有两个解决方案来读取文件并将其转换为数据集。有谁能告诉我哪种解决方案更好,为什么?
解决方案1

final case class Movie(movieID: Int)

import spark.implicits._

val moviesDS1 = spark.sparkContext.textFile("file path")
                .map(x => Movie(x.split("\t")(1).toInt))
                .toDS
                .select("movieID")

解决方案2

final case class Movie(movieID: Int, Somenum1:Int, Somenum2: Int, Somenum3:Int)

import spark.implicits._
var movieSchema = Encoders.product[Movie].schema

val moviesDS2 = spark.read.options(Map("delimiter" -> "\t"))
                .schema(movieSchema)
                .csv("file path")
                .select("movieID")
jrcvhitl

jrcvhitl1#

好吧,让我们做个小测试,看看哪个更好,

final case class Movie(movieID: Int)
  exec {

    import spark.implicits._

    val moviesDS1 = spark.sparkContext.textFile("mydata.csv/Movies.csv").toDS()
      .map { x => {
        Movie(x.split("\t")(0).toInt)

      }
      }
      .select("movieID").show(false)
   // moviesDS1.show(false)
  }
  final case class Movie1(movieID: Int, Somenum1: Int, Somenum2: Int, Somenum3: Int)
  exec {
    var movieSchema = Encoders.product[Movie1].schema

    val moviesDS2 = spark.read.options(Map("delimiter" -> "\t"))
      .schema(movieSchema)
      .csv("mydata.csv/Movies.csv")
      .select("movieID")
    moviesDS2.show(false)
  }

exec Method将以纳秒为单位测量时间。。。

/**
    *
    * @param f
    * @tparam T
    * @return
    */
  def exec[T](f: => T) = {

    val starttime = System.nanoTime()
    println("t = " + f)
    val endtime = System.nanoTime()
    val elapsedTime = (endtime - starttime)
    //    import java.util.concurrent.TimeUnit
    //    val convertToSeconds = TimeUnit.MINUTES.convert(elapsedTime, TimeUnit.NANOSECONDS)
    println("time Elapsed " + elapsedTime)
  }

结果:

+-------+
|movieID|
+-------+
|196    |
|186    |
+-------+

t = ()
time Elapsed 5053611258
+-------+
|movieID|
+-------+
|196    |
|186    |
+-------+

t = ()
time Elapsed 573163989

结论:

根据数字,第二种方法比第一种方法更快/优化(因为573163989纳秒<5053611258纳秒)。
解决方案1我们必须负责解析和Map到相应的类,在解决方案2中,它消除了低级解析数据并将数据Map到case类。
所以解决方案2是更好的选择。
所以@quicksilvers的答案在这个测试用例中是正确的。

tquggr8v

tquggr8v2#

解决方案2总是比解决方案1至少快5倍。
解决方案2还提供了对输入数据的隐式验证,如果存在单个模式不匹配,则将所有列值标记为空。
解决方案2还使用advanceapi,它提供了类似于dataframes的解决方案,首先将数据作为rdd加载,然后将其转换为dataset。

相关问题