我位于5个节点的Spark 2.3群集上,每个节点具有12Gb的可用内存,并尝试使用大约130Gb的Parquet数据集,并在此基础上创建了一个分区的外部Hive表。
比方说,我想知道数据集中的记录数。我最初的猜测是,Spark将按分区读取数据分区,聚合当前分区以获取记录数,将结果传递给驱动程序,然后删除该分区以读取下一个分区。但是,要么这不是它的工作方式(相反,Spark会先尝试读取内存中的所有内容),要么我将其编码错误。
像sql("select count(*) from myhivetable")
这样的笨方法不起作用:作业失败,并出现Java堆空间错误。 sql("select * from myhivetable").count()
也没有(我想它们还是被编译为相同的执行计划)。
我可能会忘记蜂巢表,使用文件系统API获取包含该表的文件列表,并逐个记录记录记录,将计数加到结果中,例如fileList.foldLeft{ (recCount, file) => file.read(parquet).count + recCount}
-但是,a)此方法可能无法“扩展”到其他possilbe用例,b)我仍然认为仅使用Spark工具集应该有一种更优雅的方法。我看不到吗?
答案 0 :(得分:1)
假设每个节点有8个核心,是否可以尝试将这些参数与spark-submit
或spark-shell
一起使用:
Total memory - 5 * 12GB = 60GB
Total Cores - 5 * 8 = 40
--driver-cores 1
--driver-memory 2G
--num-executors 9
--executor-cores 4
--executor-memory 6G
如果这不起作用,您可以更改号码并重试吗?并请发布错误日志,Spark UI屏幕截图。
我不确定使用SELECT COUNT(1) FROM table
代替SELECT COUNT(*) FROM table
会有什么区别!
答案 1 :(得分:0)
您不需要群集内存即可容纳所有数据。这是实木复合地板数据,因此解压缩将需要一些内存。尝试增加执行程序内存(这是计数查询,因此驱动程序内存应该不是问题)。并且即使在此之后仍然失败,请共享堆栈跟踪。