我正在使用Lumen框架v5.8(它与Laravel相同(
我有一个命令用于读取大型XML(400Mo(并从该文件中的数据更新数据库中的数据,这是我的代码:
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->first();
if ($conditionId) {
ConditionTranslation::where(['condition_id' => $conditionId->id, 'locale' => 'fr'])->update(['name' => $name]);
$this->info(memory_get_usage());
}
}
}
}
}
因此,我必须在XML中找到每个DescriptorUI
元素,该值对应于我的类Condition
的mesh_id
属性。
因此,有了$conditionId = Condition::where('mesh_id', $meshId)->first();
,我得到了条件对象。
之后,我需要更新一个Condition
=>ConditionTranslation
的孩子。所以我只是DescriptorName
获取元素并更新ConditionTranslation
的name
字段
在脚本的末尾,您可以看到$this->info(memory_get_usage());
,当我运行命令时,该值每次都会增加,直到脚本运行非常非常慢......而且永无止境。
如何优化此脚本?
谢谢!
编辑:Laravel有没有办法预更新多个对象,并在最后只保存一次所有对象?就像Symfony的flush()
方法
有一个解决方案ON DUPLICATE KEY UPDATE
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
$keyValues = [];
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->value('id');
if ($conditionId) {
$keyValues[] = "($conditionId, '".str_replace("'","'",$name)."')";
}
}
}
}
if (count($keyValues)) {
DB::query('INSERT into `conditions` (id, name) VALUES '.implode(', ', $keyValues).' ON DUPLICATE KEY UPDATE name = VALUES(name)');
}
}