我是否必须显式使用 Dataframe 的方法来利用 Dataset 的优化?

Do I have to explicitly use Dataframe's methods to take advantage of Dataset's optimization?

要利用 Dataset 的优化,我是否必须明确使用 Dataframe's 方法(例如 df.select(col("name"), col("age") 等)或调用 any Dataset 的方法 - even RDD-like methods (e.g. filter, map, etc) 也可以优化?

Dataframe 优化通常有 3 种形式:

  1. Tungsten 内存管理
  2. Catalyst 查询优化
  3. wholestage codegen

Tungsten 内存管理

在定义RDD[myclass]时,spark并没有真正理解myclass是什么。这意味着通常每行将包含 class 的一个实例。

这有两个问题。

首先是对象的大小。 java 对象有开销。例如,包含两个简单整数的案例 class。执行一系列 1000000 个实例并将其转换为 RDD 将花费约 26MB,而使用 dataset/dataframe 执行相同操作将花费约 2MB。

此外,此内存在 dataset/dataframe 中完成后不受垃圾收集管理(它在内部由 spark 管理为不安全内存),因此 GC 性能的开销较小。

Dataset享有与DataFrame相同的内存管理优势。也就是说,在进行数据集操作时,将数据从内部(行)数据结构转换为 case class 会产生性能开销。

Catalyst 查询优化

当使用数据框函数时,spark 知道您要做什么,有时可以将您的查询修改为更高效的等效查询。

例如,假设您正在做类似的事情: df.withColumn("a",lit(1)).filter($"b" < ($"a" + 1)).

基本上你是在检查是否 (x < 1 + 1)。 Spark 足够聪明,可以理解这一点并将其更改为 x<2.

使用数据集操作时无法完成此类操作,因为 spark 不了解您正在执行的函数的内部结构。

wholestage codegen

当 spark 知道您在做什么时,它实际上可以生成更高效的代码。在某些情况下,这可以将性能提高 10 倍。

这也不能在数据集函数上完成,因为 spark 不知道函数的内部结构。