在我的symfony2命令中,我正在運行一個腳本,它將數十萬個URL(以字符串形式)插入到文檔中。在Symfony2中mongodb批量插入的最佳做法
這裏是我正在使用的2個文件的基本結構。在程序運行之前,有成千上萬已經MongoDB的內部ParentDocuments的,但零個ChildDocuments:
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();
}
當我運行這個簡單的命令,寫入速度首先是令人難以置信的快速。但是,在插入數百萬行的情況下,寫入速度變得非常慢。在命令運行10分鐘後,每秒寫入速度低於1,這使得代碼非常無效。
我第一次嘗試解決這個問題的方法是在使用$dm->clear();
刷新後清除文檔管理器,但這意味着文檔管理器將失去跟蹤當前ParentDocument的情況。所以我的解決辦法是這樣的:
$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中插入數百萬行,而讀/寫速度變慢的最佳做法是什麼?
數字。謝謝! –