Лучшая практика для массовых вставок mongodb в Symfony2Php

Кемеровские программисты php общаются здесь
Ответить
Anonymous
 Лучшая практика для массовых вставок mongodb в Symfony2

Сообщение Anonymous »

В моей команде symfony2 я запускаю скрипт, который вставляет в документ сотни тысяч URL-адресов (в виде строк).

Вот основные структуры 2 документа, которые я использую. Перед запуском программы в mongodb уже есть тысячи родительских документов, но нет дочерних документов:

Код: Выделить всё

ParentDocument:
$id:id
$subDocument:OneToManyReference(ChildDocument)
$etc:everythingelse

ChildDocument:
$id:id
$url:string
$parentDocument:ManyToOneReference(ParentDocument)
И мой командный код:

Код: Выделить всё

$dm = $this->getContainer()->get('doctrine_mongodb.odm.document_manager');
$parentDocuments = $dm->repository('My:Bundle:ParentDocument')->findAll();
while ($parentDocument = $parentDocuments->getNext()) {
//Returns an array of hundreds of thousands urls
$urls = $this->somehowFetchUrlsRelatedToTheParentDocument($parentDocument);
foreach ($urls as $url) {
$subDocument = new SubDocument();
$subDocument->setUrl($url);
$subDocument->setParentDocument($parentDocument);
$dm->persist($subDocument);
}
$dm->flush();
}
Когда я запускаю эту простую команду, скорость записи поначалу невероятно высока. Однако в случае вставки миллионов строк скорость записи становится значительно медленнее. Скорость записи составляет всего 1 запись в секунду после выполнения команды в течение 10 минут, что делает код крайне неэффективным.

Моя первая попытка решить эту проблему заключалась в очистке документа менеджер документов сразу после его очистки с помощью $dm->clear();
Но это означало, что менеджер документов потеряет текущий родительский документ. Итак, мое решение было таким:

Код: Выделить всё

$dm = $this->getContainer()->get('doctrine_mongodb.odm.document_manager');
$parentDocumentCursors = $dm->repository('My:Bundle:ParentDocument')->findAll();
$parentDocuments = array();
while ($parentDocument = $parentDocumentCursors->getNext()) {
array_push($parentDocuments, $parentDocument);
}
$dm->clear();
unset($dm);
$dm = $this->getContainer()->get('doctrine_mongodb.odm.document_manager');
foreach ($parentDocuments as $parentDocument) {
$urls = $this->somehowFetchUrlsRelatedToTheParentDocument($parentDocument);
foreach ($urls as $url) {
$subDocument = new SubDocument();
$subDocument->setUrl($url);
$subDocument->setParentDocument($parentDocument);
$dm->persist($subDocument);
}
$dm->flush();
$dm->clear();
}
Это решило проблему. Скорость записи была стабильно высокой на протяжении всего выполнения программы, и миллионы строк можно было вставлять без постепенной задержки.

Однако это выглядит как плохая практика и хак быстрого исправления. Как лучше всего вставлять миллионы строк в Symfony2 с помощью диспетчера документов без снижения скорости чтения/записи?

Подробнее здесь: https://stackoverflow.com/questions/135 ... n-symfony2
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Php»