Масштабирование MySQL и map/reduce (Java EE)
egslava
Дата: 14.02.2013 22:28:55
Здравствуйте!
В качестве дипломной работы выбрал себе задание, не расчитав силы. Суть, на самом деле, довольно проста: есть социальная сеть, нужно свести пользователей по интересам. Как это работает:
Есть таблица:
Пользователь
УвлечённостьКнигами
УвлечённостьКомпьютерами
В ней два пользователя:
Пользователь1
УвлечённостьКнигами: 10
УвлечённостьКомпьютерами: 100
Пользователь2
УвлечённостьКнигами: 60
УвлечённостьКомпьютерами: 90
Есть функция расстояния между этими двумя пользователями:
|10-60|*k1 + |100-90|*k2 = 50 k1 + 10 k2.
Где k1 и k2 - некие коэффициенты. Пусть они будут равны 1 и 2, соответственно.
Тогда расстояние (d) будет равно 50 + 20 = 70.
Вот суть в том, что если мы найдём d для каждого пользователя, то отсортировав по d, мы сможем отсортировать пользователей "по схожести". Однако есть мнение, что подобные выборки могут проходить очень медленно.
Ключевой момент так же в том, что в MySQL я не разбираюсь тольком. Я его использовал только на третьем курсе, нужно было сделать на PHP сервер для чатика и я использовал там от силы таблиц 8-12 с простенькими запросиками на бесплатном хосте. Разумеется, ни о какой высокой нагрузке и речи не шло, т.е. я банально "не ориентируюсь" - 1000 пользователей - это много или мало? А 10000, а миллион? Поэтому моё решение изначально должно хорошо масштабироваться. Но пока что мне кажется, что просто доставить пару серверов не получится. Во-первых, насколько я знаю, MySQL не имеет поддержки шардинга из коробки, во-вторых, простым шардингом здесь дело не обойдётся - каждый раз нужен проход по всем записям таблицы. Т.е. здесь нужен именно Map/Reduce.
Казалось бы, здесь надо использовать MongoDB, ведь у неё есть поддержка как шардинга и репликации, так и MapReduce из коробки. Но я хочу использовать именно MySQL, потому что по монге работы (вакансий) нет, а в дальнейшем хочется иммигрировать. Т.е. хочется чтобы, приехавши в чужую страну, работа была. И тут MySQL сильно впереди (2400 вакансий против 100).
Кроме того, хочется использовать Java EE 6 (по тем же причинам), но неизвестно, как у Mongo с этим.
Слышал, что-то, что hadoop позволяет как-то использовать MySQL для обработки больших массивов данных, но, к сожалению, времени очень мало (примерно 2-3 часа в сутки), чтобы глубоко разобраться, а сдавать надо уже через две недели.
Вопросы: что всё-таки лучше использовать в моём случае? Что лучше почитать про шардинг и map/reduce в MySQL?
miksoft
Дата: 14.02.2013 23:21:45
Насчет шардинга и map/reduce не подскажу, но думается мне, что тут можно попробовать использовать RTree индексы.
См.
FAQ: Нахождение записей, где заданное значение находится между значениями полейТолько предварительно я бы предложил внести коэффициенты внутрь модулей и хранить "увлечённости" уже помноженными на свой коэффициент.
P.S. вот, сейчас написал, но уже сомнения взяли... но оставлю, может, кому-то мысль удастся развить.
DBConstructor
Дата: 15.02.2013 02:07:34
egslava, не изобретайте велосипед! Ваша задача решается проще.
Ваши так называемые "коэффициенты", ни что иное, как очередность порядка сортировки (приоритетность полей сортировки).
Соответственно:
SELECT * FROM `Пользователь` ORDER BY `УвлечённостьКомпьютерами`, `УвлечённостьКнигами`;
Все похожие пользователи будут рядом.
А если уж Вам невмоготу запариться с "коэффициентами", то попробуйте:
SELECT `ФИО`,
`УвлечённостьКомпьютерами` * 100 + `УвлечённостьКнигами` * 10 + `УвлечённостьБабами` AS `Коэффициент`
FROM `Пользователь`;
Отсортируйте результат по возрастанию коэффициента и получите тоже самое, что и в первом случае.
А еще можете для разнообразия применить формулу детерминанты матрицы с разными парами пользователей, и потом их сравнивать. )
DBConstructor
Дата: 15.02.2013 02:29:08
И вообще, подобные идеи решаются совсем другими способами.
Создаете справочник увлечений и таблицу соответствия пользователей и увлечений;
На таблицу соответствия вешаете триггер проверки, чтобы сумма всех увлечений = 100 (100%);
При подборе для каждого пользователя "пары" сначала определяете приоритетность его увлечений по их значениям (по убыванию);
Полученную приоритетность используете для сортировки по убыванию результата выборки прочих пользователей. Самый верхний результат будет самым похожим.
egslava
Дата: 15.02.2013 08:47:05
DBConstructor, спасибо большое за ответ! :)
Но, к сожалению, либо Вы меня, либо я Вас, но не поняли :(
Смотрите, в моём случае, функция расстояния - это функция от двух пользователей. Иными словами, есть три пользователя:
u1, u2, u3, u4. Для них будет
f(u1, u2), f (u1, u3), f(u1, u4),
f(u2, u3), f(u2, u4),
f(u3, u4)
(забыл сказать, не помню, как называется это свойство но f(u1,u2) = f(u2, u1) в моём случае).
Тут меня озарило и сначала показалось, что Вы правы, но ничего в сообщении стирать не стал
Да, с сортировками у Вас отличная идея, тем не менее она будет давать (как мне кажется), немного не тот результат.
Для краткости изложения, предположим, что у нас в таблице хранятся числа. Каждая цифра - отдельный столбец.
Данный человек:
3456789
Ищет пару среди:
5456789 "первый" вариант. d = 5-3 + 4-4 + 5-5 + 6-6 + 7-7 + 8-8 + 9-9 = 2
4999900 "второй" вариант. d = 4-3 + 9-4 + 9-5 + 9-6 + 9-7 + 8-0 + 9-0 = 32
Несмотря на то, что у первого варианта d намного меньше, он пойдёт вторым по очереди, т.к. 5 > 4 (он проигрывает по первому столбцу).
Потом Вы предлагаете решать задачу "влоб", я думаю, что таким методом надо заранее задумываться о масштабировании :) Т.к. БД (по идее) никак не сможет такие запросы оптимизировать - тут ни индексов, ничего. Получается ого-го сколько операций на каждый запрос.
Этот вариант самый приемлимый, но, в этом случае, хотелось бы каких-нибудь простых, но с примерами, ссылок на настройку шардинга в MySQL без геморроя :)
Честно говоря, следующий Ваш пост не понял совсем :(
> При подборе для каждого пользователя "пары" сначала определяете приоритетность его увлечений по их значениям (по убыванию);
Приоритета увлечений нет. Не понял, зачем там триггер еще, но не суть.
Самое дельное, как я понял, это высчитывать коэффициент в теле запроса, либо в хранимой процедуре какой-нибудь. Вопрос тогда такой: как всё это дело легко и просто отмасштабировать?
netwind
Дата: 15.02.2013 11:39:14
egslava, шардинг без геморроя не бывает.
есть mysql ndb cluster - более менее скрытый автоматический шардинг, но это немного другой софт, а не обычный mysql. Со своими особенностями и не всегда работающим map/reduce. Правда, там это называется condition pushdown и было реализовано до того как map/reduce стало мейнстримом. Данные разделятся будут по первичному ключу.
egslava
Дата: 15.02.2013 22:00:08
netwind,
Благодарю, спасибо за название отличной технологии :)
Не изучал глубоко - только завтра смогу попытаться поднять кластер из трёх машин и побомбить его запросами :)
Пока что хотелось бы узнать, может, подскажете чего. Дело в том, что я в Java EE ни в зуб ногой, соответственно, интересно узнать - должны ли возникнуть проблемы при использовании MySQL ndb cluster в Java EE или нет?
На сайте ни рыба ни мясо: мол проблем возникать не должно, но нормально, если они возникнут :)
Если не трудно - расскажите чуть поподронее про MySQL ndb Cluster. Как я понял, что это почти тот же MySQL в использовании, только с несколькими дополнительными фишками. Ну и разворачивать надо не только mysqld, но еще и менеджера с дата-нодами. В остальном много различий?
netwind
Дата: 16.02.2013 00:43:17
egslava, ndb-кластер благодаря sql-нодам выглядит как обычный mysql с тем же протоколом.