集合性能问题
这两天在修改以前的一个功能模块的时候,发现有一短代码执行效率非常低,正常只需要几毫秒就能执行完,却花了好几秒,
一步步追踪下去,发现问题出在集合查询。
$this->countryReplenish->where('partsId', $asp->partsId)
->where('brandId', $asp->brandId)
->where('countryId', $asp->countryId)
->first();
$this->countryReplenish
是个大小为3W左右的集合。我这样做的理由是为了减少访问数据库次数,从数据库里边把需要用到的数据全部读出来,以后要用的时候只需要用集合操作。用 microtime(true)
对这段代码计时,1.34秒:scream:
多试几次,还是需要1秒多的时间
当把集合查询改为数据库查询的时候,效率就很高了,几毫秒就搞定
查看一下 Collection
where()
方法的源码
public function where($key, $operator, $value = null)
{
.
.
.
return $this->filter($this->operatorForWhere($key, $operator, $value));
}
查看 operatorForWhere()
方法,返回一个闭包
protected function operatorForWhere($key, $operator, $value)
{
return function ($item) use ($key, $operator, $value) {
$retrieved = data_get($item, $key);
.
.
.
}
其中 data_get()
函数包含一个 while 循环,时间复杂度为O(n)。
然后结合 filter()
方法过滤,返回一个新集合
public function filter(callable $callback = null)
{
if ($callback) {
return new static(Arr::where($this->items, $callback));
}
return new static(array_filter($this->items));
}
因此当调用多个where()
方法时,时间复杂度为O(n m k)。
按照这样的思路,尝试只调用一次 where()
方法,尴尬的是,还是花了1秒多,效率和多次调用 where()
方法差不多。
那么问题来了,难道集合操作的效率真的很低吗?
经过查找资料,答案就在附言中。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: