I want to understand the concept of merge-sort join in Spark in depth. I understand the overall idea: this is the same approach as in merge sort algorithm: Take 2 sorted datasets, compare first rows, write smallest one, repeat. I also understand how I can implement distributed merge sort.
But I cannot get how it is implemented in Spark with respect to concepts of partitions and executors.
Here is my take.
- Given I need to join 2 tables A and B. Tables are read from Hive via Spark SQL, if this matters.
- By default Spark uses 200 partitions.
- Spark then will calculate join key range (from minKey(A,B) to maxKey(A,B) ) and split it into 200 parts. Both datasets to be split by key ranges into 200 parts: A-partitions and B-partitions.
- Each A-partition and each B-partition that relate to same key are sent to same executor and are sorted there separatelt from each other.
- Now 200 executors can join 200 A-partitions with 200 B-partitions with guarantee that they share same key range.
- The join happes via merge-sort algo: take smallest key from A-partition, compare with smallest key from B-partition, write match, or iterate.
- Finally, I have 200 partitions of my data which are joined.
Does it make sense?
Issues: Skewed keys. If some key range comprises 50% of dataset keys, some executor would suffer, because too many rows would go to the same partition. It can even fail with OOM, while trying to sort too big A-partition or B-partition in memory (I cannot get why Spark cannot sort with disk spill, as Hadoop does?..) Or maybe it fails because it tries to read both partitions into memory for joining?
So, this was my guess. Could you please correct me and help to understand the way Spark works?