我一直在尝试使用Apache Spark来查看它是否可用于为我们存储在Elasticsearch集群中的数据创建分析引擎。我发现,对于任何重要的RDD大小(即数百万条记录),即使最简单的操作也需要超过一分钟。
例如,我制作了这个简单的测试程序:
package es_spark;
import java.util.Map;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.elasticsearch.spark.rdd.api.java.JavaEsSpark;
public class Main {
public static void main (String[] pArgs) {
SparkConf conf = new SparkConf().setAppName("Simple Application");
conf.set("es.nodes", pArgs[0]);
JavaSparkContext sc = new JavaSparkContext(conf);
long start = System.currentTimeMillis();
JavaPairRDD<String, Map<String, Object>> esRDD = JavaEsSpark.esRDD(sc, "test3");
long numES = esRDD.count();
long loadStop = System.currentTimeMillis();
JavaRDD<Integer> dummyRDD = esRDD.map(pair -> {return 1;});
long numDummy = dummyRDD.count();
long mapStop = System.currentTimeMillis();
System.out.println("ES Count: " + numES);
System.out.println("ES Partitions: " + esRDD.getNumPartitions());
System.out.println("Dummy Count: " + numDummy);
System.out.println("Dummy Partitions: " + dummyRDD.getNumPartitions());
System.out.println("Data Load Took: " + (loadStop - start) + "ms");
System.out.println("Dummy Map Took: " + (mapStop - loadStop) + "ms");
sc.stop();
sc.close();
}
}
我在一个带有3个从站的火花簇上运行它,每个从站有14个核心和49.0GB的RAM。使用以下命令:
./bin/spark-submit --class es_spark.Main --master spark://<master_ip>:7077 ~/es_spark-0.0.1.jar <elasticsearch_main_ip>
输出结果为:
ES Count: 8140270
ES Partitions: 80
Dummy Count: 8140270
Dummy Partitions: 80
Data Load Took: 108059ms
Dummy Map Took: 104128ms
在800多万条记录上执行虚拟地图作业需要1.5分钟以上。鉴于地图工作什么也没做,我觉得这个表现出奇的低。我做错了什么,或者这是关于Spark的正常表现吗?
我也尝试过对--executor-memory
和--executor-cores
进行调整,没有多大区别。
答案 0 :(得分:0)
一般情况下,除非您看到OOM故障或重要GC或溢出到磁盘作为瓶颈,否则不值得更改执行程序内存。当你改变它时,你也应该减少spark.memory.fraction。对于你的工作,它几乎不可能提供帮助。
Spark的启动成本使得对于较小的数据加载而言效率相对较低。您应该能够将启动时间优化到不到一分钟,但对于超大批量加载而言,它仍然更加实用,而不是实时分析。
我建议您使用DataFrame API而不是RDD。对于上面的简单示例操作,它无关紧要,但随着事情变得更加复杂,您更有可能从性能优化中受益。
e.g。 library(reshape2)
mydfl <- melt(mydf)
mydfl$ind <- with(mydfl, ave(C1, C1, variable, FUN = seq_along))
dcast(mydfl, C1 + ind ~ variable, sum,
margins = c("C1", "ind", "variable"))
# C1 ind X1 X2 (all)
# 1 a 1 12 1 13
# 2 a 2 14 2 16
# 3 a (all) 26 3 29
# 4 b 1 16 3 19
# 5 b 2 11 4 15
# 6 b 3 8 5 13
# 7 b (all) 35 12 47
# 8 (all) (all) 61 15 76
要解决导致速度缓慢的问题,您可以查看Spark UI。你真的得到并行吗?所有工作在大致相同的时间内执行了吗?另一个可能的缓慢来源是群集和ES服务器之间的网络问题。
答案 1 :(得分:0)
鉴于地图工作什么都不做,发现这个性能出乎意料地低。
地图工作没有做任何事情。它必须从Elastic搜索中获取完整的数据集。因为数据没有缓存,所以它会发生两次,每次操作一次。这个时间还包括一些初始化时间。
总的来说,你衡量:
和一些次要的事情,如: