Apache spark 为什么在Spark中缓存数据集之前查询速度更快?

Apache spark 为什么在Spark中缓存数据集之前查询速度更快?,apache-spark,caching,parquet,Apache Spark,Caching,Parquet,我试图比较基于拼花文件和缓存数据集的数据集上Spark查询的性能 令人惊讶的是,对拼花地板数据集的查询比对缓存数据的查询要快。我认为至少有两个理由不应该这样做: 缓存的数据在内存中,而拼花地板文件不在内存中。它在我的SSD上 我希望缓存的数据以优化的格式用于spark查询 我在一个300MB的拼花地板9M行上做了这个小基准测试,只对查询时间进行计时,而不是缓存数据的时间: def benchmarkSum(ds: org.apache.spark.sql.DataFrame): Double =

我试图比较基于拼花文件和缓存数据集的数据集上Spark查询的性能

令人惊讶的是,对拼花地板数据集的查询比对缓存数据的查询要快。我认为至少有两个理由不应该这样做:

缓存的数据在内存中,而拼花地板文件不在内存中。它在我的SSD上 我希望缓存的数据以优化的格式用于spark查询 我在一个300MB的拼花地板9M行上做了这个小基准测试,只对查询时间进行计时,而不是缓存数据的时间:

def benchmarkSum(ds: org.apache.spark.sql.DataFrame): Double = {
  var begin = System.nanoTime();
  for (int <- 1 to 1000) {
     ds.groupBy().sum("columnName").first()
  }
  return (System.nanoTime() - begin) / 1000000000.0;
}    

val pqt = spark.read.parquet("myfile.parquet");
benchmarkSum(pqt) // 54s

var cached = pqt.cache()
cached.groupBy().sum("columnName").first() // One first call to triggers the caching before benchmark.
benchmarkSum(cached) // 77s
对Parquet的查询耗时54秒,而对缓存数据集的查询耗时77秒。 我在spark shell中做这个基准测试,它有8个内核和10GB内存


那么,为什么使用缓存数据对我的列求和会比较慢呢?我做错什么了吗?

在第一条pqt语句中尝试.cache

这就是我所做的:

已将78MB文本文件上载到Databricks文件存储。 在标准Databricks Community Edition安装程序上运行修改后的基准测试。 修改你的

ds.groupBy().sum("value").first()
对于一个简单的数据帧计数也执行了1000次-看看复制专家怎么说

    df.count
然后,我在两次单独运行中运行了以下内容,但没有重新启动mini Cluster:

 // RUN 1
 val pqt = spark.read.text("/FileStore/tables/TTT.txt")
 benchmarkSum(pqt)

我跑了1分806秒,连续跑了2次860秒

我跑了2分51秒,50秒连续跑了2次

所以,有一个稍微不同的方法,但是.cache是放在前面的,但我觉得这并不能解释它。除了我观察到的.cache有了显著的改进-这与您的场景和结果不同


我不知道该怎么做——只是在我的场景中,这些东西似乎是按照建议工作的。这可能是催化剂/发动机罩下钨优化的一个缺陷吗?我不时看到一些关于这方面的帖子。

可能是我错了——我在工作之间这么做——但通常会尽早打开缓存。我认为第二个缓存会重新读取拼花+缓存。我下班后会查的。确实看了一眼太快了。我不是那个把-1放进去的人,对不起。我认为你需要使用拼花文件来重现我的问题,而不是txt,因为拼花有一个更优化的格式,如果声明了,不需要道歉。但更重要的是,尽管我还没有得到答案,但关键是我的测试支持您的断言,即缓存在许多情况下都能正常工作。也就是说,还有其他一些线索指出了这方面的问题。我会在这个周末将文件转换为拼花地板,并重新尝试,尽管不仅仅是计数。第二点是为什么这被归类为重复。无论如何,如果你找到了答案,我很想知道。在数据帧的情况下,依赖计数和缓存是一种不好的做法。@Philantrover你是说我永远不应该缓存数据帧,或者永远不应该使用计数触发缓存吗?我试图删除计数或用其他调用替换它,结果是类似的。我查看了这个问题,但不能完全推断它严格地说是重复的方法措辞,事实上,这是一个非常有用的问题,我认为我已在我的问题中删除了对.count的调用。这不是重复的,我不知道另一个问题如何回答这个问题。我正在比较缓存数据集和基于拼花文件的数据集的行为,而其他问题是关于何时触发数据集求值。first将在第一个分区上触发缓存。它不会缓存完整的数据集。此外,缓存的数据也在内存中—不一定。它可能在磁盘上。我希望缓存的数据以优化的格式用于spark查询—您正在应用全局聚合。与先构建复杂而昂贵的结构相比,只读取一组值和聚合值要便宜得多。即使在一次运行中忽略所有54秒和77秒,也不是一个有统计意义的结果。Spark可以显示更高的方差,这取决于许多因素。
 // RUN 2
 val pqt = spark.read.text("/FileStore/tables/TTT.txt").cache
 benchmarkSum(pqt)