使用Distinct列过滤结果会大大减慢执行速度

时间:2017-10-01 13:25:01

标签: apache-spark apache-spark-sql spark-dataframe

我用spark编写了一个自定义RDD提供程序,并在sql查询下测试了它的执行时间。我不确定此提供程序的内部机制是否与该问题相关,但基本上它用于从本地和远程文件中读取数据。

问题:使用' distinct'运行查询关键字(无论是否为聚合问题)都会对查询的性能产生严重影响。

示例:

查询:从表中选择sourceip,sourceport,destinationport,其中destinationport = 80 执行时间:31527毫秒

查询:从destinationport = 80的事件中选择不同的sourceip,sourceport,destinationport 执行时间:57856毫秒

这个结果适用于非常少量的数据,当我尝试在中等大小的数据集上运行时,Spark会破坏“太多打开的文件”。 日志是:

/tmp/spark-a47f859b-2a1f-4466-8333-0bf40c3968eb/executor-9c98264a-23a8-49b8-ab6f-ddf7349e0155/blockmgr-b73fc639-8705-4956-8652-e7300b35527a/3f/temp_shuffle_b4afe57f-9db1-4653-91c0-22d207933748 (Too many open files)

对于透视图,使用distinct使用5分钟的数据破坏集群,其中没有区别服务器成功运行2天查询。

任何可能导致此问题的想法?

P.S。我使用以下方法验证了打开文件的数量及其限制:

open files: `lsof | wc -l` resulted in ~1.4M
max open files: `cat /proc/sys/fs/file-max` resulted in 9-42M (depending on machine - master had 9M)

2 个答案:

答案 0 :(得分:0)

以下两个步骤可帮助您调试问题:

1)distinct()肯定是跨分区进行洗牌。要查看更多正在发生的事情,请在RDD上运行.toDebugString吗?

2)你能检查你的工作是否正确并行使用Spark UI进行检查?

同时检查您的分区是否有偏差,here is link for further reading

答案 1 :(得分:0)

当然,如果您的查询有所不同,那么您的查询将会变慢。

select sourceip, sourceport, destinationport from table where destinationport=80

这是一个简单的选择过滤器查询。所以它不需要任何洗牌。 Spark将执行谓词下推并仅使用过滤操作提供结果

尽管

select distinct sourceip, sourceport, destinationport from events where destinationport=80 

在这里你有所不同。这基本上要求火花做洗牌。它将首先筛选出结果,然后计算每个结果的哈希值,然后执行reduce操作以删除重复的结果(相同的哈希多行归结为一行)

现在shuffle是一个相对昂贵的操作,因为它需要通过网络发送数据,因此第二个查询将比前者慢得多