所以我正在学习从Apache Spark中获取ElasticSearch的数据。 让我们说我已经与拥有“用户”的ElasticSearch建立了联系。索引。
sqlContext = SQLContext(sc)
usersES=sqlContext.read.format('org.elasticsearch.spark.sql').option('es.nodes','mynode').load('users/user')
解释(usersES)告诉我这个:
==物理计划==
扫描ElasticsearchRelation(地图(es.nodes - > mynode, es.resource - > 用户/用户),org.apache.spark.sql.SQLContext @ 6c78e806,无)[关于#145,#活动146,bdate#147 UID#148]
当我使用过滤器时:
usersES.filter(usersES.uid==1566324).explain()
==物理计划==过滤器(uid#203L = 1566324) + - 扫描ElasticsearchRelation(地图(es.nodes - > mynode,es.resource - > 用户/用户),org.apache.spark.sql.SQLContext @ 6c78e806,无)[关于#145,#活动146,bdate#147,#UID 148] PushedFilters:[EqualTo(uid,1566324)]
如您所见,Spark优雅地将过滤器推送到ElasticSearch,使索引搜索变得快速而舒适。
但是当我尝试使用其他数据框加入usersES时,我始终会遇到同样的问题: Spark扫描整个ElasticSearch索引,而不是推送我提供的任何过滤器。 例如:
a = sc.parallelize([1566324,1566329]).map(Row('id')).toDF()
a.join(usersES, usersES.uid==a.id).explain()
所示:
SortMergeJoin [id#210L],[uid#203L]: - 排序[id#210L ASC],false,0: + - TungstenExchange hashpartitioning(id#210L,200),None:+ - ConvertToUnsafe:+ - Scan ExistingRDD [id#210L] + - 排序[uid#203L ASC],false,0 + - TungstenExchange hashpartitioning(uid#203L,200),None + - ConvertToUnsafe + - 扫描ElasticsearchRelation(地图(es.nodes - > mynode,es.resource - > 用户/用户),org.apache.spark.sql.SQLContext @ 6c78e806,无)[关于#145,#活动146,bdate#147,#UID 148]
请告诉我,是否可以在连接中的Elasticsearch内推送过滤器?
答案 0 :(得分:4)
这是一种预期的行为,是的,elaticsearch-hadoop连接器支持下推谓词,但是当你加入时没有推送。
这是因为连接操作不知道如何在数据帧中对键进行分区。
默认情况下,此操作将散列两个数据帧的所有键,将具有相同键哈希值的所有元素通过网络发送到同一台计算机,然后将该元素与该计算机上的相同键连接在一起。
这就是为什么在没有推断谓词的情况下获得执行计划的原因。
编辑:自2.1版 IN 子句以来,连接器似乎支持。如果你的DataFrame不是很大,你应该使用它。