Spark 中的 DataSet 和 DataFrame 是概念上相似的数据结构,都是优化的数据集和存储在分布式内存上的集合。尽管它们看起来相同,但是在内部实现和使用方式上,它们还是有一些主要的区别的。
- 类型检查:
DataFrame 基于 Catalyst Optimizer,可以利用其中的模式信息做到强类型检查和编译器优化。而 DataSet 是强类型的,这会在编译时进行类型检查。当类型不匹配时,编译器会在编译时就直接报错。
- 强类型和弱类型:
DataFrame 是弱类型的,它在特定情况下隐式转换数据类型,我们也可以使用 Cast
函数来转换。DataSet 是强类型的,编译时就已经确定了类型。
- 调用函数:
DataFrame 有两种主要的 API,一种是 DataFrame API,另一种是 SQL。所有的 DataFrame API 都支持基于列的转换,而 SQL 仅支持 SQL 操作。DataSet 支持方法调用,可以使用各种函数进行转换。
- 序列化:
DataSet 仅序列化成 Java 对象或者二进制数据,而 DataFrame 利用 Tungsten 和 Catalyst 进行序列化。Tungsten 是 Spark 1.5 新特性,基于 Unsafe 操作追求极致的执行效率;Catalyst 则是 Spark 2.0 新增的高效 SQL 执行器。
结论:
- 如果需要从 Python 或者 R 中访问数据,推荐使用 DataFrame。
- 如果需要数据类型检查或直观的面向对象的 API,并且有计划输出到编译时确定的代码格式(如常规 Scala 软件开发项目或者期望代码更容易维护,除非数据格式更改仍然需要更新的花费较少的测试代码(如 Spark 规范项目或持续交付流程)),则应使用 DataSet。
- 如果数据本身的结构并没有太多复杂性,可以更轻松地与 DataFrame 进行交互。一旦遇到过度复杂的结构或无法进行首次检查的结构(例如数据 schema 引用动态配置或直接从外部源读取的情况),则应考虑转换为 DataSet 以进行强检查和更清晰的编译时报告。