hashjoin
join是作为业务开发绕不开的SQL话题,无论是传统的数据库join,还是大数据里的join。 做过Spark/flink流处理的应该都用过一种流表和维表的join,维表对于Spark来说可以是driver端获取后广播到每个Executor,然后在executor端执行流表task的时候join,其实大多数是个hashmap,而很多时候这个维表比较大会存储于redis/hbase。Flink进行维表join可以用的方式比较多了,比如直接open方法里从外部加载的静态hashmap,这种就无法更新,因为Flink不像Spark可以每个批次或者若干批次加载一次维表。也可以使用LRU+异步IO+外部存储来实现join,这样就实现了对外部更新的感知。甚至也可以使用Flink的广播功能实现join操作。 上面所说的就是比较常见的hashjoin的简单表达,将维表通过join的条件key构建为一个hashtable,就拿java 8的HashMap来说吧,就是一个数组+链表(链表过长会变为红黑树),数组下标就是key,数组存储的是value的指针。 join的时候主表通过join条件构建key去,hashmap里查找。Spark BroadCastHashJoin
翻过源码之后你就会发现,Spark 1.6之前实现BroadCastHashJoin就是利用的Java的HashMap来实现的。大家感兴趣可以去Spark 1.6的源码里搜索BroadCastHashJoin,HashedRelation,探查一下源码。 具体实现就是driver端根据表的统计信息,当发现一张小表达到广播条件的时候,就会将小表collect到driver端,然后构建一个HashedRelation,然后广播。