Spark SQL:使用“order by”提高缓存内存占用

Posted

技术标签:

【中文标题】Spark SQL:使用“order by”提高缓存内存占用【英文标题】:Spark SQL: Cache Memory footprint improves with 'order by' 【发布时间】:2016-03-26 16:05:37 【问题描述】:

我有两种情况,我有23 GB 分区parquet 数据并预先读取少量columnscaching 以便稍后触发一系列后续查询。

设置

集群:12 节点 EMR Spark 版本:1.6 Spark 配置:默认 运行配置:两种情况相同

案例 1

val paths = Array("s3://my/parquet/path", ...)
val parqFile = sqlContext.read.parquet(paths:_*)
parqFile.registerTempTable("productViewBase")
val dfMain = sqlContext.sql("select guid,email,eventKey,timestamp,pogId from productViewBase")
dfMain.cache.count

SparkUI,读取的输入数据为6.2 GB,缓存对象为15.1 GB

案例 1

val paths = Array("s3://my/parquet/path", ...)
val parqFile = sqlContext.read.parquet(paths:_*)
parqFile.registerTempTable("productViewBase")
val dfMain = sqlContext.sql("select guid,email,eventKey,timestamp,pogId from productViewBase order by pogId")
dfMain.cache.count

SparkUI,读取的输入数据为6.2 GB,缓存对象为5.5 GB

对此行为有任何解释或代码参考吗?

【问题讨论】:

【参考方案1】:

其实比较简单。正如您在 SQL 指南中所读到的:

Spark SQL 可以使用内存中的列格式缓存表...Spark SQL 将仅扫描所需的列并自动调整压缩率

排序列式存储的好处在于它非常容易压缩典型数据。排序时,您会得到这些相似记录块,甚至可以使用非常简单的技术(例如 RLE)将它们压缩在一起。

这是一个在具有列式存储的数据库中实际上经常使用的属性,因为它不仅在存储方面非常高效,而且在聚合方面也非常有效。

sql.execution.columnar.compression 包涵盖了 Spark 柱状压缩的不同方面,正如您所见,RunLengthEncoding 确实是可用的压缩方案之一。

所以这里有两个部分:

Spark 可以调整压缩method on the fly based on the statistics:

Spark SQL 将根据数据的统计信息自动为每一列选择一个压缩编解码器。

排序可以将相似的记录聚集在一起,从而提高压缩效率。

如果列之间存在一些相关性(当不是这种情况?),即使是基于单个列的简单排序也会产生相对较大的影响并提高不同压缩方案的性能。

【讨论】:

不是列式存储方面的专家,但在一列上排序数据导致 3 倍压缩似乎是个奇迹。你能分享我可以调试/实验的任何细节或代码参考吗? @Mohitt 是否涉及任何序列化? 无显式序列化。一切都是默认的。 您可以尝试在每个示例中使用 Kryo 进行实验吗?原始缓存会带来开销,并且在持久化后可能会占用 2-4 倍的空间。 @Mohitt 我已经扩展了答案,但这取决于不同的因素。就个人而言,我建议浏览一些由教授撰写的有关内存数据管理的书籍。哈索普拉特纳。这些通常非常昂贵,但许多章节已作为课程材料免费提供。

以上是关于Spark SQL:使用“order by”提高缓存内存占用的主要内容,如果未能解决你的问题,请参考以下文章

sql 数据量很大 ,为啥加了order by速度变慢了?

提高Order by语句查询效率的两个思路

sql 排序,order by 按时间

sql注入中order by的作用

sql语句执行顺序之group by、order by

sql [mysql:ORDER BY中的CASE]在mysql的ORDER BY中使用CASE。 #mysql #sql