2015-05-18 45 views
3

我想用doctrine batch insert processing來優化插入大量的實體。問題出在Clear方法。它說這個方法分離了由EntityManager管理的所有實體。所以,我應該做的情況下,我有一個父實體,其中有許多孩子,每個孩子都有自己的孩子的,就像這樣:Doctrine EntityManager在嵌套實體中清除方法

  • riseSession
    • 軌道

因此,我已1個rideSession,3個軌道和每個軌道具有用於isntance 2 0 00分。我可以在上一個負責保存點的循環中使用批處理。但是,如果我使用清晰的方法,那麼如何設置父母的點數和曲目?清除方法會將它們分開,對吧?

+0

你的問題是什麼?你有什麼?你想實現什麼?如果您現在將所有對象都放在內存中,爲什麼要使用這種批處理方法?這是爲了優化管理內存:當你的所有對象不能存儲在內存中的時候。所以你需要創建對象,然後在循環中分離所有實體(釋放內存)。它在PHP腳本中優化內存。 –

+0

因此,如果我在內存中有40000個對象(從JSON解碼實體),那麼我可以肯定,當我調用$ em-> flush()服務器不會與OOM異常崩潰?因爲這是我從你的評論中瞭解到的。 – Tom

回答

4

很快你會達到內存限制。 flush()批量的想法是好的,但您需要在每批次的末尾使用clear()EntityManager以釋放已用內存。

但在您的情況下,如果您在$entityManager->clear();之後致電$child->setParent($parent);,您將擁有ORMInvalidArgumentException(也稱爲「通過關係創建新實體」)。

問題是$parent現在處於detached狀態UnitOfWork。所以你需要把它重新放在managed狀態。這可以通過使用$entityManager->merge();或僅使用$parentRepository->find($parent->getId());來完成。

只要確保將所有實體調出managed狀態後每個clear()萬一你打算稍後使用它們。

+0

這正是我所說的。這正是我的問題。謝謝@Valentas! – Tom

1

如果你已經將所有40000對象加載到內存中,那麼你可以直接使用代碼而不清除。清理實體管理器用於優化PHP腳本中的內存。如果您有足夠的內存來存儲所有對象,則根本不需要清除實體管理器。

要在這種情況下優化內存,您可以在每次持續之後unset($entity)

並且爲了適應數據庫連接帶寬,您可以將幾個實體分組,如示例。

$batchSize = 20; 
for ($i = 1; $i <= 10000; ++$i) { 
    $em->persist($entities[$i]); 
    unset($entities[$i]); 
    if (($i % $batchSize) === 0) { 
     $em->flush(); 
    } 
} 
$em->flush(); //Persist objects that did not make up an entire batch 
+0

我想這裏我們有3個內存用例:json_decode()返回的數組,在循環中創建的實體對象,同時解析前面提到的數組和EntityManager與持久實體。所以最好的方法可能是使用清晰的同時使用flush,就像@Valentas寫道的那樣,並且使用未設置從json_decode拉取的數組元素,並且在持久化之後可能爲null實體?我將Valentas的回覆標記爲接受答案,因爲我的問題是指這個問題,但也感謝您的幫助。 – Tom