Эффективность потока данных Hadoop для "клиентов, которые купили x, также купили y" - PullRequest
4 голосов
/ 19 марта 2012

Я начинаю работать с Hadoop и работаю над созданием цепочки MapReduce для "клиентов, которые купили x, также купили y", где y - это продукт, который чаще всего покупается с помощью x. Я ищу совет по повышению эффективности этой задачи, под которым я подразумеваю уменьшение объема данных, перетасовываемых с узлов сопоставления на узел редуктора . Моя цель немного отличается от других сценариев "клиент купил х", потому что я просто хочу сохранить наиболее часто покупаемый продукт для данного продукта, а не список продуктов, приобретенных с данным продуктом, ранжированным по частоте .

Я слежу за этим сообщением в блоге , чтобы руководствоваться моим подходом.

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

Допустим, мой начальный набор данных - это таблица SQL purchases_products, таблица соединения между покупкой и продуктами, которые были куплены в этой покупке. Я введу select x.product_id, y.product_id from purchases_products x inner join purchases_products y on x.purchase_id = y.purchase_id and x.product_id != y.product_id в свою операцию MapReduce.

Моя стратегия MapReduce состоит в том, чтобы сопоставить product_id_x, product_id_y с product_id_x_product_id_y, 1 и затем суммировать значения на моем шаге уменьшения. После этого я могу разделить ключи и сохранить пары обратно в таблицу SQL.

Моя проблема с этой операцией заключается в том, что она тасует потенциально огромное количество строк, хотя размер набора результатов, который я хочу получить, составляет всего count(products) большой. В идеале, я бы хотел, чтобы шаг объединителя сузил количество перемещаемых рядов до редукторов на этом этапе, но я не вижу способа сделать это надежно.

Это просто ограничение выполняемой задачи или существуют приемы Hadoop для организации рабочего процесса, которые помогут мне уменьшить перемешивание данных во время второго шага? Подходит ли в этом случае мое беспокойство о размере шаффла или нет?

Спасибо!

1 Ответ

1 голос
/ 21 марта 2012

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

Сохраняйте карту пар продуктов для подсчета частоты в вашем картографе, и вместо того, чтобы записывать каждую пару продуктов и значение 1 в контекст, накапливайте их в карте. Когда карта достигнет предопределенного размера, сбросьте карту в выходной контекст. Вы даже можете использовать карту LRU для хранения наиболее часто наблюдаемых пар на карте и записывать эти «просроченные» записи, когда они вытесняются.

Пример, адаптированный для примера подсчета слов, см. http://www.wikidoop.com/wiki/Hadoop/MapReduce/Mapper#Map_Aggregation

Конечно, если у вас огромный набор продуктов или случайные пары продуктов, это не сильно вас спасет. Вам также необходимо понять, насколько большой может быть ваша карта, прежде чем истечет доступная память JVM.

Вы также можете уменьшить количество данных, хранящихся в ваших выходных объектах Key / Value:

  • Являются ли идентификаторы продуктов целыми числами (имеют ли они относительно низкую стоимость - могут ли они выиграть от того, что они написаны как VIntWritable, а не IntWritable?)
  • Если они являются целыми числами, вы записываете ключ пары продукта в виде String представления идентифицированных сцепленных идентификаторов или используете собственный ключ с двумя полями int (следовательно, записываете 4 + 4 байта, а не потенциально большее число, если вы используете строковое представление)
  • Вы записываете значение '1' как VIntWritable?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...