0
假設我有6000個值,並且我正在執行一個for
循環,並使用Symfony2 + Doctrine執行INSERT
或UPDATE
操作,這是執行這些語句的最佳/正確方法並保持良好的性能水平?Doctrine2性能:插入/更新多行
首先
for ($i = 0; $i < 6000; $i++) {
// SELECT HERE - need to find if Territory already exists
$entTerritory = $em->getRepository('PDOneBundle:Territory')->findOneBy(array('veeva_territory_id' => $soqlObj2['records'][$i]['Id']));
if (!$entTerritory) {
// if there is no territory, then we add
$newTerritory = new Entity\Territory();
// we set the values from veeva
if ($soqlObj2['records'][$i]['Id'] !== null || $soqlObj2['records'][$i]['Id'] !== "") {
$newTerritory->setVeevaTerritoryId($soqlObj2['records'][$i]['Id']);
$newTerritory->setName($soqlObj2['records'][$i]['Name']);
$em->persist($newTerritory);
$em->flush(); // ---> FLUSH HERE
}
$terrArr[] = $newTerritory->getId();
$terrFailArr[] = $soqlObj2['records'][$i]['Name'];
} else {
$lastModifiedDate = new \DateTime(
$soqlObj2['records'][$i]['LastModifiedDate']
);
if ($lastModifiedDate > $entTerritory->getUpdatedAt()) {
// obtained a territory, we update its data
$entTerritory->setName($soqlObj2['records'][0]['Name']);
}
$em->flush(); // ---> FLUSH HERE
$terrArr[] = $entTerritory->getId();
}
}
二
for ($i = 0; $i < 6000; $i++) {
// SELECT HERE - need to find if Territory already exists
$entTerritory = $em->getRepository('PDOneBundle:Territory')->findOneBy(array('veeva_territory_id' => $soqlObj2['records'][$i]['Id']));
if (!$entTerritory) {
// if there is no territory, then we add
$newTerritory = new Entity\Territory();
// we set the values from veeva
if ($soqlObj2['records'][$i]['Id'] !== null || $soqlObj2['records'][$i]['Id'] !== "") {
$newTerritory->setVeevaTerritoryId($soqlObj2['records'][$i]['Id']);
$newTerritory->setName($soqlObj2['records'][$i]['Name']);
$em->persist($newTerritory);
}
$terrArr[] = $newTerritory->getId();
$terrFailArr[] = $soqlObj2['records'][$i]['Name'];
} else {
$lastModifiedDate = new \DateTime(
$soqlObj2['records'][$i]['LastModifiedDate']
);
if ($lastModifiedDate > $entTerritory->getUpdatedAt()) {
// obtained a territory, we update its data
$entTerritory->setName($soqlObj2['records'][0]['Name']);
}
$em->flush(); // ---> FLUSH HERE
$terrArr[] = $entTerritory->getId();
}
}
$em->flush(); // ---> FLUSH FOR INSERT HERE
三
for ($i = 0; $i < 6000; $i++) {
// SELECT HERE - need to find if Territory already exists
$entTerritory = $em->getRepository('PDOneBundle:Territory')->findOneBy(array('veeva_territory_id' => $soqlObj2['records'][$i]['Id']));
if (!$entTerritory) {
// if there is no territory, then we add
$newTerritory = new Entity\Territory();
// we set the values from veeva
if ($soqlObj2['records'][$i]['Id'] !== null || $soqlObj2['records'][$i]['Id'] !== "") {
$newTerritory->setVeevaTerritoryId($soqlObj2['records'][$i]['Id']);
$newTerritory->setName($soqlObj2['records'][$i]['Name']);
$em->persist($newTerritory);
}
$terrArr[] = $newTerritory->getId();
$terrFailArr[] = $soqlObj2['records'][$i]['Name'];
} else {
$lastModifiedDate = new \DateTime(
$soqlObj2['records'][$i]['LastModifiedDate']
);
if ($lastModifiedDate > $entTerritory->getUpdatedAt()) {
// obtained a territory, we update its data
$entTerritory->setName($soqlObj2['records'][0]['Name']);
}
$terrArr[] = $entTerritory->getId();
}
}
$em->flush(); // ---> FLUSH FOR INSERT AND UPDATE HERE
我還發現圍繞一個主題這here他們說:
當你有更新多個實體,從 檢索它們所有的數據庫,並遍歷ORM實體被稱爲壞 做法。
你不應該做這樣的:
$friend = $em->getReference('Octivi\Entity\User', $friendId); $users =
$this->findAll();
foreach ($users as $user) {
$user->setFriend($friend);
$em->persist($user); }
$em->flush();
相反,你應該依靠UPDATE查詢:
$qb->update('Octivi:User', 'u')
->set('u.friend', $friendId)
->getQuery()->execute();
多虧了這一點,我們只執行一個SQL UPDATE語句,而不是每個用戶實體的N更新。
那麼,最好的方法是什麼?爲什麼?
您需要理論批處理。點擊此處:http://doctrine-orm.readthedocs.org/en/latest/reference/batch-processing.html – reverbnation