提升PHP DOM-XML查询性能:7000条数据查询耗时70秒如何优化到5秒内
性能问题根源
你当前的实现每次循环都执行一次全文档XPath查询,总共执行7000+次遍历DOM树的操作,时间复杂度为O(数组长度 * XML节点数),是耗时过高的核心原因。
最优优化方案(耗时可低至1秒内)
只遍历XML一次,构建person-name到id的映射表,再用映射表匹配查询数组,时间复杂度降到O(XML节点数 + 数组长度),是性能最高的实现:
$dom = new DOMDocument; $dom->load('myxml.xml'); $xp = new DOMXPath($dom); // 一次性获取所有带person-name属性的unit节点 $units = $xp->query("//unit[@person-name]"); $nameToId = []; foreach ($units as $unit) { $name = $unit->getAttribute('person-name'); $id = $unit->getAttribute('id'); // 如果一个name对应多个id,就改成$nameToId[$name][] = $id $nameToId[$name] = $id; } $arrayIds = [ 'A001', ..., 'A7500' ]; $data = []; foreach ($arrayIds as $arrayId) { if (isset($nameToId[$arrayId])) { $data[] = $nameToId[$arrayId]; } }
如果你的业务场景允许一个person-name对应多个id,把映射表的赋值逻辑改成数组追加即可。
次选方案:单次XPath批量查询
你也可以把所有要查询的ID拼接成XPath条件,仅执行一次查询:
$dom = new DOMDocument; $dom->load('myxml.xml'); $xp = new DOMXPath($dom); $arrayIds = [ 'A001', ..., 'A7500' ]; // 对ID转义避免XPath注入,同时格式化查询条件 $quotedIds = array_map(fn($id) => '"' . addslashes($id) . '"', $arrayIds); $expression = "//unit[@person-name=(" . implode(',', $quotedIds) . ")]/@id"; $col = $xp->query($expression); $data = []; foreach ($col as $node) { $data[] = $node->nodeValue; }
该方案性能也远高于原实现,不过在ID数量过多时,XPath表达式解析的开销会略高于第一种方案。
内容的提问来源于stack exchange,提问作者mending3
相关产品推荐
相关产品推荐

