我在PySpark中创建了两个RDD,其数据是从HBase中提取的。我想收集具有相同行键的项目,存储项目,然后搜索与每个项目相关联的值。理想情况下,我将结果存储在pyspark.sql对象中,因为我想将Levenshtein距离应用于其内容。
详细说明:
在HBase中,我有位置数据,其中行键是给定区域的geohash,并且在列中,该区域中有多个场所,位置上有更多详细信息(带有描述和其他文本数据的json)。 我有两个HBase表,两个位置可以相同。我想搜索这两个RDD中的数据,检查类似的地理位置并将结果存储在新的数据结构中。
我不想重新发明轮子而且我刚刚开始学习Spark,因此我想知道:做这项任务的最佳方法是什么?内置函数rdd.intersection是一个很好的解决方案吗?
答案 0 :(得分:3)
已编辑:实际上,多亏了@ Aneel的评论,我可以纠正一些错误。
实际上对RDD进行join调用会给出相同的结果(连接在RDD的第一列完成,值是两个RDD的其余列的元组),作为调用带有Spark SQL的JOIN
放弃,而不是像之前指出的那样执行cogroup
,因为@Aneel在一个单独的键下指出了cogroup
壁球键值对。
现在另外一点,我尝试了@Aneel的方法,以及上面的要点,并尝试对它进行基准测试,这是结果,使用数据库'社区版(非常小的集群,6GB的内存,1个核心和Spark 2.1),这里是link。 (代码也在帖子的末尾)
结果如下:
实际上,对于小型数据集来说,RDD似乎比数据帧更快,但是一旦达到阈值(大约250k记录),Dataframes连接开始变得更快
现在正如@Aneel建议的那样,请记住我做了一个非常简单的例子,你可能想对你自己的数据和环境进行一些测试(我的2个列表中没有超过10M行,因为已经花了2.6分钟来初始化。)
初始化代码:
#Init code
NUM_TESTS=100
from random import randint
l1 = []
l2 = []
import timeit
for i in xrange(0, 10000000):
t = (randint(0,2000), randint(0,2000))
v = randint(0,2000)
l1.append((t,v))
if (randint(0,100) > 25): #at least 25% of the keys should be similar
t = (randint(0,2000), randint(0,2000))
v = randint(0,2000)
l2.append((t,v))
rdd1 = sc.parallelize(l1)
rdd2 = sc.parallelize(l2)
Spark SQL测试:
#Test Spark SQL
def callable_ssql_timeit():
df1 = spark.createDataFrame(rdd1).toDF("id", "val")
df1.createOrReplaceTempView("table1")
df2 = spark.createDataFrame(rdd2).toDF("id", "val")
df2.createOrReplaceTempView("table2")
query="SELECT * FROM table1 JOIN table2 ON table1.id=table2.id"
spark.sql(query).count()
print(str(timeit.timeit(callable_ssql_timeit, number=NUM_TESTS)/float(NUM_TESTS)) + "s")
RDD加入测试:
#Test RDD join
def callable_rdd_timeit():
rdd1.join(rdd2).count()
print(str(timeit.timeit(callable_rdd_timeit, number=NUM_TESTS)/float(NUM_TESTS)) + "s")
答案 1 :(得分:2)
既然你想使用pyspark.sql DataFrames,那么在开始时如何将RDD转换为它们呢?
df1 = spark.createDataFrame(rdd1)
df1.createOrReplaceTempView("table1").toDF("geohash", "other", "data", )
df2 = spark.createDataFrame(rdd2)
df2.createOrReplaceTempView("table2").toDF("geohash", "other", "data", "fields")
spark.sql("SELECT * FROM table1 JOIN table2 ON table1.geohash = table2.geohash").show()
如果要对类似(不相同)的地理位置进行操作,可以注册用户定义的函数来计算它们之间的距离。