Best Practice für Mongodb-Masseneinfügungen in Symfony2Php

PHP-Programmierer chatten hier
Anonymous
 Best Practice für Mongodb-Masseneinfügungen in Symfony2

Post by Anonymous »

In meinem Symfony2-Befehl führe ich ein Skript aus, das Hunderttausende URLs (als String) in ein Dokument einfügt.

Hier sind die Grundstrukturen von 2 Dokumente, die ich verwende. Bevor das Programm ausgeführt wird, befinden sich bereits Tausende von ParentDocuments in der Mongodb, aber keine ChildDocuments:

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

ChildDocument:
$id:id
$url:string
$parentDocument:ManyToOneReference(ParentDocument)


Und mein Befehlscode:

$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();
}


Wenn ich diesen einfachen Befehl ausführe, ist die Schreibgeschwindigkeit zunächst unglaublich hoch. Beim Einfügen von Millionen von Zeilen werden die Schreibgeschwindigkeiten jedoch deutlich langsamer. Nur 1 Schreibvorgang pro Sekunde, nachdem der Befehl 10 Minuten lang ausgeführt wurde, was den Code äußerst ineffektiv macht.

Mein erster Versuch, dieses Problem zu beheben, bestand darin, das Dokument zu löschen Manager direkt nach dem Leeren mit $dm->clear();
Dies bedeutete jedoch, dass der Dokumentmanager den Überblick über das aktuelle ParentDocument verlor. Meine Lösung war also diese:

$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();
}


Das hat das Problem gelöst. Die Schreibgeschwindigkeiten waren während der gesamten Ausführung des Programms konstant hoch und Millionen von Zeilen konnten ohne allmähliche Verzögerung eingefügt werden.

Dies fühlt sich jedoch wie eine schlechte Praxis an und ein schneller Lösungs-Hack. Was ist die beste Vorgehensweise zum Einfügen von Millionen Zeilen in Symfony2 mithilfe des Dokumentmanagers, ohne dass die Lese-/Schreibgeschwindigkeit langsamer wird?

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post