Объединение двух наборов данных в Mapreduce/Hadoop

кто-нибудь знает, как реализовать операцию естественного соединения между двумя наборами данных в Hadoop?

более конкретно, вот что мне точно нужно сделать:

у меня есть два набора данных:

  1. информация о точке, которая хранится как (tile_number, point_id:point_info) , это пары ключ-значение 1:n. Это означает, что для каждого tile_number может быть несколько point_id: point_info

  2. информация о строке, которая хранится как (tile_number, line_id:line_info) , это снова пары ключ-значение 1:m, и для каждого tile_number может быть более одного line_id:line_info

как вы можете видеть, tile_numbers одинаковы между двумя наборами данных. теперь мне действительно нужно объединить эти два набора данных на основе каждого tile_number. Другими словами, для каждого tile_number у нас есть N point_id:point_info и m line_id:line_info. Что я хочу сделать, так это присоединиться ко всем парам point_id: point_info со всеми парами line_id: line_info для каждого tile_number


чтобы уточнить, вот пример:

для пар точек:

(tile0, point0)
(tile0, point1)
(tile1, point1)
(tile1, point2)

для пар:

(tile0, line0)
(tile0, line1)
(tile1, line2)
(tile1, line3)

что я хочу, так это следующее:

для плитки 0:

 (tile0, point0:line0)
 (tile0, point0:line1)
 (tile0, point1:line0)
 (tile0, point1:line1)

для плитки 1:

 (tile1, point1:line2)
 (tile1, point1:line3)
 (tile1, point2:line2)
 (tile1, point2:line3)

3 ответов


используйте картограф, который выводит заголовки в качестве ключей и точек/линий в качестве значений. Необходимо различать выходные значения точек и выходные значения линий. Например, вы можете использовать специальный символ (хотя бинарный подход был бы намного лучше).

таким образом, вывод карты будет чем-то вроде:

 tile0, _point0
 tile1, _point0
 tile2, _point1 
 ...
 tileX, *lineL
 tileY, *lineK
 ...

после этого, на редукторе, ваш входной сигнал будет иметь эту структуру:

 tileX, [*lineK, ... , _pointP, ...., *lineM, ..., _pointR]

и вам придется взять значения, разделяющие точки и линии, сделайте кросс-продукт и выведите каждую пару кросс-продукта, например:

tileX (lineK, pointP)
tileX (lineK, pointR)
...

если вы уже можете легко различать значения точек и значения строк (в зависимости от спецификаций вашего приложения), вам не нужны специальные символы (*,_)

относительно кросс-продукта который вы должны сделать в редукторе: Сначала вы перебираете весь список значений, разделяете их на 2 списка:

 List<String> points;
 List<String> lines;

затем выполните кросс-продукт через 2 вложенных циклов for. Затем повторите полученный список и для каждого элемента выведите:

tile(current key), element_of_the_resulting_cross_product_list

таким образом, в основном у вас есть два варианта здесь.Уменьшите боковое соединение или сопоставьте боковое соединение .

здесь ваш ключ группы - "плитка". В одном редукторе вы получите весь выход из пары точек и пары линий. Но вам придется либо кэшировать пару точек, либо пару линий в массиве. Если какая-либо из пар(точка или линия) очень велика, что ни один не может поместиться в памяти временного массива для одного ключа группы(каждая уникальная плитка), то этот метод не будет работать для вас. Помнить вам не нужно удерживать обе пары ключей для одного группового ключа ("плитка") в памяти, одного будет достаточно.

Если обе пары ключей для одного ключа группы большие, то вам придется попробовать map-side join.Но у него есть некоторые особые требования. Однако вы можете выполнить эти требования, выполнив предварительную обработку данных через некоторые задания map/reduce с одинаковым количеством редукторов для обоих данных.


Я нашел это полезным

присоединяется к простой карте Reduce или MultipleInputs

http://kickstarthadoop.blogspot.in/2011/09/joins-with-plain-map-reduce.html