php - Doctrine2 性能 : Insert/Update multiple rows

标签 php mysql performance symfony doctrine-orm

假设我有 6000 个值,我正在对它们执行 for 循环,并使用 Symfony2 + 执行 INSERTUPDATE 操作 + Doctrine,这是执行这些语句并保持良好性能水平的最佳/正确方法?

首先

   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他们说:

When you have to update multiple entities, retrieving them all from the database and iterating over ORM entities is known as a bad practice.

You should never do like:

$friend = $em->getReference('Octivi\Entity\User', $friendId); $users =
$this->findAll();

foreach ($users as $user) {
    $user->setFriend($friend);
    $em->persist($user); }

$em->flush(); 

Instead, you should rely on the UPDATE query:

$qb->update('Octivi:User', 'u')
     ->set('u.friend', $friendId)
     ->getQuery()->execute(); 

Thanks to it, we only execute one SQL UPDATE statement instead of N-updates for each User entity.

那么,什么是最好的方法,为什么?

最佳答案

在我看来,使用 SQL 是批处理的最佳/性能方式。众所周知,Doctrine 会占用大量内存,并可能很快达到允许的内存大小。

关于php - Doctrine2 性能 : Insert/Update multiple rows,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30905885/

相关文章:

PHP 检查数据库中的项目

php - 如何在 prestashop 1.7 中向自定义页面发送 ajax 请求

php - MySQL select 3 UNIQUE random ID rows fast WHERE

php - 从两个 mysql 表中选择,其中列值相似并且 id 从上一页检索

python - python 的 numpy.ndarray 和 list 数据类型之间的区别

php - 正则表达式表示一个单词,但如果他们正在创建另一个单词,则避免使用它

php - Google 日历事件创建和 Google 企业帐户

mysql - 如何获取查询的动态列

performance - 使用 CLRS 代码和 Robert Sedgewick 代码进行插入排序的运行时间差异

c# - 使用 Enumerable 和 Lambda 过滤文件列表并删除不需要的扩展名