为什么spark sql查询第一次和第二次执行的时间不同?

2023-12-28

我正在使用 Spark sql 对 parquet 数据源运行一些聚合查询。

我的 parquet 数据源包括一个表,其中包含以下列:id int、时间时间戳、位置 int、counter_1 long、counter_2 long、...、counter_48。总数据大小约为887 MB。

我的spark版本是2.4.0。我在一台机器上运行一主一从(4核,16G内存)。

使用 Spark-shell,我运行了 Spark 命令:

spark.time(spark.sql("SELECT location, sum(counter_1)+sum(counter_5)+sum(counter_10)+sum(counter_15)+sum(cou
nter_20)+sum(counter_25)+sum(counter_30)+sum(counter_35 )+sum(counter_40)+sum(counter_45) from parquet.`/home/hungp
han227/spark_data/counters` group by location").show())

执行时间为17s。

我第二次运行类似的命令(仅更改列):

spark.time(spark.sql("SELECT location, sum(counter_2)+sum(counter_6)+sum(counter_11)+sum(counter_16)+sum(cou
nter_21)+sum(counter_26)+sum(counter_31)+sum(counter_36 )+sum(counter_41)+sum(counter_46) from parquet.`/home/hungp
han227/spark_data/counters` group by location").show())

执行时间约为3s。

我的第一个问题是:为什么它们不同?我知道这不是数据缓存,因为镶木地板格式。是关于重用查询计划之类的东西吗?

我做了另一个测试:第一个命令是

spark.time(spark.sql("SELECT location, sum(counter_1)+sum(counter_5)+sum(counter_10)+sum(counter_15)+sum(cou
nter_20)+sum(counter_25)+sum(counter_30)+sum(counter_35 )+sum(counter_40)+sum(counter_45) from parquet.`/home/hungp
han227/spark_data/counters` group by location").show())

执行时间为17s。

在第二个命令中,我更改了聚合函数:

spark.time(spark.sql("SELECT location, avg(counter_1)+avg(counter_5)+avg(counter_10)+avg(counter_15)+avg(cou
nter_20)+avg(counter_25)+avg(counter_30)+avg(counter_35 )+avg(counter_40)+avg(counter_45) from parquet.`/home/hungp
han227/spark_data/counters` group by location").show())

执行时间约为5s。

我的第二个问题是:为什么第二个命令比第一个命令快,但执行时间差异却比第一个场景略小?

最后,我有一个与上述场景相关的问题:大约有 200 个公式,例如:

formula1 = sum(counter_1)+sum(counter_5)+sum(counter_10)+sum(counter_15)+sum(cou
nter_20)+sum(counter_25)+sum(counter_30)+sum(counter_35 )+sum(counter_40)+sum(counter_45)

formula2 = avg(counter_2)+avg(counter_5)+avg(counter_11)+avg(counter_15)+avg(cou
nter_21)+avg(counter_25)+avg(counter_31)+avg(counter_35 )+avg(counter_41)+avg(counter_45)

我必须经常运行以下格式:

select formulaX,formulaY, ..., formulaZ from table where time > value1 and time < value2 and location in (value1, value 2...) group by location

我的第三个问题是:有没有办法优化性能(使用过一次的查询如果将来再次使用应该会更快)? Spark 会自我优化还是我必须编写一些代码,更改配置?


这称为交换重用。当 Spark 运行混洗(即聚合、连接)时,它会在本地工作节点上存储混洗数据的副本以供重用。这是内部控制的行为,最终用户无法直接影响。如果您发现不断重复使用数据的特定部分(或查询结果),您可以考虑使用 cache() 显式缓存它。但是,请记住,虽然这允许 Spark 重用缓存结果以获得更快的查询性能(当且仅当缓存查询的分析器计划与新查询匹配时),但过度使用 CACHE 可能会导致大量不同的性能问题。

一个不好的例子是,当您的数据集非常大时,可能会导致磁盘溢出问题。也就是说,数据集不适合集群的可用内存,需要写入速度较慢的硬盘。

另一个不好的例子是当您的查询只需要访问缓存数据的子集时。通过将整个数据集缓存在内存中,Spark 被迫执行完整的内存表扫描。这不仅浪费资源,而且与根本不使用缓存相比,还会导致查询性能变慢。

最好的做法是使用您自己的一些示例查询进行尝试和错误,查看 Spark UI 并检查是否存在磁盘溢出或大量输入数据扫描的迹象。

每个查询/数据组合都是唯一的,因此您需要进行一些试验才能找到适合您自己的工作负载的最佳性能调整方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么spark sql查询第一次和第二次执行的时间不同? 的相关文章

随机推荐