如何优化PHP中用于跨API商品同步的嵌套foreach循环
优化方案
1. 替换嵌套循环为哈希索引查找
原来的嵌套循环时间复杂度为O(nm),n是外部API商品数,m是站点商品数,数据量增长后耗时会指数级上升。改为先遍历一次站点商品,以sku为键构建哈希索引,之后遍历外部商品时直接用O(1)复杂度查找匹配项,整体时间复杂度降到O(n+m)*。
2. 替换单条更新为批量接口请求
原代码每匹配到一个商品就发起一次PUT请求,HTTP请求的握手、响应开销占总耗时的90%以上。改为使用WooCommerce原生的批量更新接口products/batch,一次请求提交多条更新数据,大幅减少HTTP请求次数。
3. 可选长期优化
- 改为增量同步,每次只拉取上次同步时间之后变更的商品,减少处理数据量
- 超大数量场景下可将同步任务拆分后放入异步队列执行,避免单次请求超时
100个商品场景耗时测算
假设两边各有100个商品,匹配率80%,单次HTTP请求平均耗时200ms,PHP单步运算耗时1微秒:
- 原方案耗时:100*100次比较(0.01s) + 80次PUT请求(16s) + 两次拉取API耗时(2s)= 约18s,很容易触发30s/60s的服务端超时阈值
- 优化后方案耗时:200次哈希构建+匹配运算(0.0002s) + 4次批量请求(0.8s) + 两次拉取API耗时(2s)= 约2.8s,耗时仅为原方案的15%左右
优化后代码示例
$webServiceProducts = $this->webserviceGetData('GetAllData',$webserviceProductBody); $websiteProducts = $this->wooGetReq('products'); $updateCounter = 0; // 构建sku到站点商品的哈希索引 $websiteProductMap = []; foreach ($websiteProducts as $wp) { $websiteProductMap[strval($wp->sku)] = $wp; } $updateBatch = []; $batchSize = 20; // 可根据接口限制调整批量大小 foreach ($webServiceProducts as $wsProduct) { $currentSku = strval($wsProduct->ProductId); if (isset($websiteProductMap[$currentSku])) { $updateCounter++; $updateBatch[] = [ 'id' => $websiteProductMap[$currentSku]->id, 'name' => $wsProduct->Name, 'sku' => $currentSku ]; // 达到批量阈值则发送请求 if (count($updateBatch) >= $batchSize) { $this->wooPutReq('products/batch', ['update' => $updateBatch]); $updateBatch = []; } } } // 发送剩余的更新数据 if (!empty($updateBatch)) { $this->wooPutReq('products/batch', ['update' => $updateBatch]); } echo $updateCounter.' Items Updated';
内容的提问来源于stack exchange,提问作者Hamed Zargar
相关产品推荐
相关产品推荐

