Dataframe Spark SQL 1.6.0-用于简单查询的大量内存使用

Dataframe Spark SQL 1.6.0-用于简单查询的大量内存使用,dataframe,hive,apache-spark-sql,spark-dataframe,Dataframe,Hive,Apache Spark Sql,Spark Dataframe,我正在使用EMR4.3上的Spark 1.6来查询~15TB的数据,这些数据属于hive元存储中的一个表(由S3中的gzip拼花文件支持)。对于我的群集,我有一个r3.8X大型主节点和15个r3.8X大型核心节点(3.6TB RAM、9.6TB SSD) 大约15 TB的数据包含在90亿行中。每行约有15列存储长度为5-50的字符串,一列包含约30个字符串的数组,每个字符串包含10-20个字符。数组中仅存储约100万个唯一字符串。我所要做的只是计算数组列中的唯一字符串,但随着我不断得到:OutO

我正在使用EMR4.3上的Spark 1.6来查询~15TB的数据,这些数据属于hive元存储中的一个表(由S3中的gzip拼花文件支持)。对于我的群集,我有一个r3.8X大型主节点和15个r3.8X大型核心节点(3.6TB RAM、9.6TB SSD)

大约15 TB的数据包含在90亿行中。每行约有15列存储长度为5-50的字符串,一列包含约30个字符串的数组,每个字符串包含10-20个字符。数组中仅存储约100万个唯一字符串。我所要做的只是计算数组列中的唯一字符串,但随着我不断得到:OutOfMemoryError:无法在执行器上创建新的本机线程,我的内存似乎已经用完了。由于内存不足错误,任务失败,执行器被禁用,然后作业失败

当我查询5-10TB的数据时,它可以工作。我一定不能正确理解存储在内存中的内容(这正是我试图弄明白的)。顺便说一句,使用上面的集群,我正在设置:

spark.executor.memory 30g
spark.executor.cores 5
spark.executor.instances 90 // 6 instances per r3.8xlarge host
我不认为Spark SQL将中间表存储在内存中。由于唯一字符串不超过1M,我认为带计数的字符串应该很容易放入内存中。问题是:

val initial_df = sqlContext.sql("select unique_strings_col from Table where timestamp_partition between '2016-09-20T07:00:00Z' and '2016-09-23T07:00:00Z'")
initial_df.registerTempTable("initial_table") // ~15TB compressed data to read in from S3

val unique_strings_df = sqlContext.sql("select posexplode(unique_strings_col) as (string_pos, string) from initial_table").select($"string_pos", $"string")
unique_strings_df.registerTempTable("unique_strings_table")  // ~70% initial data remaining at this point

val strings_count_df = sqlContext.sql("select string, count(*) as unique_string_count from unique_strings_table where string_pos < 21 group by string order by unique_string_count desc") // ~50% initial data remaining at this point
strings_count_df.write.parquet("s3://mybucket/counts/2016-09-20-2016-09-23")
val initial_df=sqlContext.sql(“从表中选择唯一的_字符串_col,其中时间戳_分区在'2016-09-20T07:00:00Z'和'2016-09-23T07:00:00Z'之间”)
要从S3读入的初始df.RegisterEmptable(“初始表格”)//~15TB压缩数据
val unique_strings_df=sqlContext.sql(“从初始_表中选择posexplode(unique_strings_col)作为(string_pos,string”)。选择($“string_pos”,$“string”)
唯一字符串df.registerTempTable(“唯一字符串表”)//~70%的初始数据此时仍保留
val strings\u count\u df=sqlContext.sql(“选择字符串,count(*)作为unique\u strings\u表中的unique\u strings\u count,其中string\u pos<21按字符串顺序分组,按unique\u string\u count desc”)//~50%的初始数据保留在此点
strings_count_df.write.parquet(“s3://mybucket/counts/2016-09-20-2016-09-23”)

压缩的拼花地板文件很小(比如每个5 MB)。看起来它们可以一次读取一个,过滤并与计数一起存储。我缺少什么?

因此,我需要有足够的磁盘+内存空间来存储初始RDD。如果我在创建临时表之前在初始RDD中进行更多的预先筛选,我就能够成功地运行查询。耶