Spark中的快速条件连接

时间:2016-05-25 10:31:30

标签: database hadoop join apache-spark mapreduce

我正在尝试使用条件查询在Spark中快速丰富。

我有两个key / val数据集:“Event Data”和“Session Map”。 “会话映射”用于找出谁在两个时间戳之间使用给定的IP。 “事件数据”是一个大型事件集合,带有IP和时间戳,需要与“会话映射”相关联以丰富用户名。

是否有一种有效的方法可以在Spark或其他方面丰富事件数据与会话映射?

会话地图:

IP -> timestamp
192.168.0.l, 2016-01-01 10:00:00
192.168.0.l, 2016-01-01 10:00:01
192.168.0.l, 2016-01-01 10:00:02
192.168.0.l, 2016-01-01 10:05:23
...
192.168.0.l, 2016-01-01 22:00:01 
192.168.0.l, 2016-01-01 22:12:35 
192.168.0.l, 2016-01-01 04:12:00
...

事件数据:

{{1}}

2 个答案:

答案 0 :(得分:1)

您可以做的是在IP上的两个集合上完全加入。这将生成一个非常大的表,然后您可以过滤以仅保留事件落在会话范围内的组合。所以:

IP_RDD = (IP,(start_time, end_time, name))
Session_RDD = (IP, timestamp)
joined_RDD = IP_RDD.join(Session_RDD)
joined_RDD = joined_RDD.filter(end_time<=timestamp<=end_time)

这个伪代码应该这样做,你需要编写一个函数来检查时间戳并将其恢复为正确的格式。我不知道这是否足够快,但除非会话start_time和end_time处于设定时间(例如每2小时一次新会议即可),我看不到更好的方法。

答案 1 :(得分:0)

我认为更简单的方法是首先使用zipWithIndex(以降低连接操作的成本):

 val SessionUnion = Session.zipWithIndex.map(x=>(x._1.IP,x._1.start_time,x._2)) //This should give you a RDD of IP,Date,Index
 val UnionEvent = Event.map(x=>(x.IP,x.timeStamp,0.toLong)).union(SessionUnion)

这基本上是一个包含所有会话和事件的平面表 - 但问题是Sessions有索引而事件只有0。

现在利用RDD中的排序

val sortAns = UnionEvent.map(x=>((x.IP,x.timeStamp),x._3)).sortBy(_._1)

这种排序应该为你调整IP和日期范围,现在你需要做的就是调整指数:

 IP1,DateFromSession1,Index1
 IP1,DateFromEvent1,0
 IP1,DateFromEvent2,0
 IP1,DateFromSession2,Index2
 ...

因此,您可以执行Foldleft,使得所有0的索引都被先前的Index替换,因此您最终得到IP1,DateFromEvent,IndexFromSession。或者我想还有其他一些有趣的方法可以做到这一点。

将索引附加到Event,您现在可以使用索引进行连接,该索引应该非常快。