Переход с Mysql на MongoDB 200 миллионов строк - PullRequest
1 голос
/ 26 июля 2011

Мы пытаемся перейти от mysql к mongodb. MySQL структура id_src int id_dest int уникальный ключ: id_src, id_dest

Это примерно 200 миллионов строк в MySQL

пример данных: {id_src, id_dest} {1,2} {1,3} {1,10} {2,3} {2,10} {4,3}

Нам нужно получить данные: {id_dest, count} {3,3} {10,2} {2,1}

Я начал воспроизводить структуру mysql в mongodb. Производительность вставки была огромной (очень хорошей): около 1 часа для вставки 200 миллионов строк.

Но мне нужно было использовать карту, чтобы получить группу. Уменьшение карты заняло около 1 часа.

Итак, я попытался создать другую структуру mongodb: {Id_dest, {id_src1, id_src2}}

Каждый документ может иметь сотню тысяч id_src.

Вот мой код insert.php

$res=mysql_unbuffered_query("select * from ids limit 10000100");  
while ($tab=mysql_fetch_array($res)) {  
$collection->update(array('_id'=>(int)$tab['id_dest']),array('$push' => array('src'=>(int)$tab['id_src'])),array("upsert" => true));  
}  

Но в этом случае производительность очень плохая, только несколько обновлений в секунду.

Я что-то не так делаю?

1 Ответ

6 голосов
/ 27 июля 2011

Перво-наперво, Map / Reduce не предназначен для анализа в реальном времени.Кроме того, MongoDB в настоящее время ограничивается одним ядром для M / R, что еще больше замедлит работу.

Так что, если вы собираетесь использовать M / R для получения данных, это не будет «в реальном времени»."оно будет обновляться каждые X минут (или часов).

Здесь есть два эффективных подхода:

  1. Инкрементальный M / R
  2. Счетчики реального времени

Опция № 1: Инкрементальное M / R

Для этой опции вы запускаете M / R один раз для всех данных.Затем, двигаясь вперед, вы запускаете M / R только для измененных данных.Если у вас есть 200 миллионов документов сейчас, у вас может быть 210 миллионов документов далее (что означает, что M / R становится еще медленнее).Но если вам нужно только запустить новые / измененные документы, то это займет намного меньше 1 часа.

Посмотрите на параметр вывода reduce в документах здесь .

Опять предпосылка заключается в том, что вы только M / R релевантные данные, и система "реуменьшает" по сравнению с существующими данными.Таким образом, вы получаете «инкрементное» M / R.

Опция № 2: Счетчики реального времени

В этом методе у вас есть две коллекции: одна дляваши данные, секунда для результата "резюме".Когда вы вставляете данные, вы также делаете приращение в сводке.

Предположим, у вас есть эти данные:

Main Collection
{src: 1, dest: 2}
{src: 1, dest: 3}
{src: 1, dest: 10}
{src: 2, dest: 3}
{src: 2, dest: 10}
{src: 4, dest: 3}

Summary Collection
{dest: 3, count: 3}
{dest: 10, count: 2}
{dest: 2, count: 1}

Вы получаете новый фрагмент данных {src: 5, dest: 2}.Вы сделаете два обновления:

db.main.insert({src: 5, dest: 2});
db.summary.update({dest: 2}, { $inc : { count: 1 } }, true); // upsert true

Вот ваши новые данные:

Main Collection
{src: 1, dest: 2}
...
{src: 4, dest: 3}
{src: 5, dest: 2}

Summary Collection
{dest: 3, count: 3}
{dest: 10, count: 2}
{dest: 2, count: 2}

Вы заметите, что мы обновили наше резюме: {dest: 2, count: 2}.

Очевидно, что здесь есть компромиссы.Вам нужно больше обновлений / вставок (2 раза), но вы получаете счетчики в реальном времени.Теперь в MongoDB нет транзакций, поэтому вам нужно будет выбрать стратегию для обеспечения того, чтобы оба обновления происходили.Есть много способов сделать это, но я не могу использовать их здесь (см. Очереди сообщений для одного метода).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...