我正在使用 Symfony 2.7 和 Doctrine 开发网络应用。 Symfony命令用于执行大量实体的更新。
我关注Doctrine guidelines并且不使用$entityManager->flush()
每个实体。
这是Doctrine示例代码:
<?php
$batchSize = 20;
for ($i = 1; $i <= 10000; ++$i) {
$user = new CmsUser;
$user->setStatus('user');
$user->setUsername('user' . $i);
$user->setName('Mr.Smith-' . $i);
$em->persist($user);
if (($i % $batchSize) === 0) {
$em->flush();
}
}
$em->flush(); //Persist objects that did not make up an entire batch
准则说:
您可能需要尝试使用批量大小来查找其大小 最适合你。较大的批量大小意味着更准备的声明 在内部重复使用,但也意味着更多的工作在冲洗期间。
所以我尝试了不同的批量大小。批处理大小越大,命令完成其任务的速度就越快。
因此问题是:大批量的缺点是什么?在所有实体更新后,为什么不再使用$entityManager->flush()
文件说,更大的批量大小&#34;意味着在冲洗期间更多的工作&#34;。但是为什么/何时这可能是一个问题?
我可以看到的唯一缺点是更新期间Exceptions
:如果脚本在保存的已更改位置之前停止,则更改将丢失。这是唯一的限制吗?
答案 0 :(得分:10)
大批量的缺点是什么?
如果为示例创建10,000个实体,则大批量可以使用大量内存。如果不以批处理方式保存实体,它们将在内存中累积,如果程序达到内存限制,则可能会导致整个脚本崩溃。
为什么不在所有实体更新后仅使用
$entityManager->flush()
这是可能的,但是在调用flush()
一次之前将10,000个实体存储在内存中将比使用100保存实体100使用更多内存。它可能还需要更多时间。
该文件只是说,较大的批量大小“意味着更多的工作时间”。但是为什么/何时这可能是一个问题?
如果您对最大批量大小没有任何性能问题,可能是因为您的数据不足以填满内存或破坏PHP的内存管理。
因此批量的大小取决于多个因素,主要是内存使用量与时间的关系。如果脚本占用太多RAM,则必须降低批处理的大小。但是使用非常小的批次可能比更大的批次花费更多的时间。因此,您必须运行多个测试才能调整此大小,以便它使用大部分可用内存但不会更多。
我没有任何证据,但我记得曾与数千家实体合作过。当我只使用一个flush()
时,我看到进度条变慢了,看起来我的程序越来越慢,因为我在内存中添加了越来越多的实体。
答案 1 :(得分:4)
如果刷新花费太多时间,则可能超过服务器的最长执行时间,并失去连接。
答案 2 :(得分:1)
根据我的经验,每批100个实体效果很好。取决于实体,200太多而其他实体,我可以做1000.
要正确批量插入,您需要以下命令:
$em->clear();
每次冲洗后。原因是Doctrine没有将它冲刷到DB中的对象释放出来。这意味着如果你不“清除”它们,内存消耗将继续增加,直到你破坏你的PHP内存限制并使你的操作崩溃。
我还建议不要将PHP内存限制增加到更高的值。如果这样做,您可能会在服务器上造成巨大的延迟,这可能会增加与服务器的连接数,然后使其崩溃。
还建议在Web Server上载表单页面之外处理批处理操作。因此,将数据保存在Blob中,然后使用Cronjob任务处理它,该任务将在所需的时间(Web服务器的峰值使用时间之外)处理批处理。
答案 3 :(得分:0)
正如Doctrine文档中所建议的那样,ORM不是批处理使用的最佳工具。
除非您的实体需要某些特定逻辑(如侦听器),否则请避免使用ORM并直接使用DBAL。