Объединение двух наборов данных в Mapreduce/Hadoop
кто-нибудь знает, как реализовать операцию естественного соединения между двумя наборами данных в Hadoop?
более конкретно, вот что мне точно нужно сделать:
у меня есть два набора данных:
информация о точке, которая хранится как (tile_number, point_id:point_info) , это пары ключ-значение 1:n. Это означает, что для каждого tile_number может быть несколько point_id: point_info
информация о строке, которая хранится как (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