Laravel orderBy 大大降低了响应速度
Laravel orderBy slowing down response greatly
省略不必要的信息table结构如下(未列出所有with关系):
products
id
launch_date
name
product_view_history
id
account_id
product_id
timestamps
我的查询不规则地花费了很长时间。通过我所做的所有分析,在 SQL 中花费的实际时间非常少(<50 ms
),但执行此代码所花费的时间在 900+ms
范围内:
$this->select('products.*', DB::raw('COUNT(product_view_history.id) as view_count'))
->leftJoin('product_view_history', 'product_view_history.product_id', '=', 'products.id', 'outer')
->groupBy('product_view_history.product_id')
->orderBy('view_count', 'DESC')
->orderBy('products.id', 'DESC')
->whereNotNull('products.launch_date')
->with(['owner.images', 'owner.star', 'owner.follows', 'owner.followers', 'company.products.alphas'])
->take(Config::get('xxxx.limits.small'))
->get();
但是,如果我注释掉 ->orderBy('view_count', 'DESC')
,此代码执行所需的时间会减少相应的 <50ms
。如果我手动将 get()
换成 toSql()
和 运行 这两个查询,我发现时间相对相似且较小。要明确测量所花费的时间不是 SQL 查询时间;我只是在完成之前和之后立即获取以毫秒为单位的时间,并记录差异。
谁能看出为什么 ->orderBy('view_count', 'DESC')
会增加将近一整秒的代码执行时间,即使 SQL 本身 not/minimally 更慢?
似乎执行原始查询和加水和加载似乎加快了查询速度。这并没有回答为什么 order by 会导致这样的问题,但它确实回答了如何解决手头的问题:
$products = self::hydrate(DB::select(
"select `products`.*, COUNT(product_view_history.id) as view_count
from `products` left join `product_view_history`
on `product_view_history`.`product_id` = `products`.`id`
where `products`.`launch_date` is not null
group by `product_view_history`.`product_id`
order by `view_count` desc, `products`.`id` desc limit {$limit}"))
->load(['owner.images', 'owner.star', 'owner.follows', 'owner.followers', 'company.products.alphas']);
对我来说,这是由于在 where 查询中使用 "wrong" 数据类型造成的。
例如,我按名为 "username" 的列进行过滤,该列是一个 varchar,但插入了一个 Int 作为过滤依据的值。
使用 orderBy 时花费了很长时间,但是当删除 orderBy 时又很快了。
解决方案至少对我来说是将用户名转换为字符串,并且 orderBy 像以前一样流畅。我不知道真正的原因,但可能 Eloquent 在使用不匹配的数据类型时进行不同的转换或排序。
省略不必要的信息table结构如下(未列出所有with关系):
products
id
launch_date
name
product_view_history
id
account_id
product_id
timestamps
我的查询不规则地花费了很长时间。通过我所做的所有分析,在 SQL 中花费的实际时间非常少(<50 ms
),但执行此代码所花费的时间在 900+ms
范围内:
$this->select('products.*', DB::raw('COUNT(product_view_history.id) as view_count'))
->leftJoin('product_view_history', 'product_view_history.product_id', '=', 'products.id', 'outer')
->groupBy('product_view_history.product_id')
->orderBy('view_count', 'DESC')
->orderBy('products.id', 'DESC')
->whereNotNull('products.launch_date')
->with(['owner.images', 'owner.star', 'owner.follows', 'owner.followers', 'company.products.alphas'])
->take(Config::get('xxxx.limits.small'))
->get();
但是,如果我注释掉 ->orderBy('view_count', 'DESC')
,此代码执行所需的时间会减少相应的 <50ms
。如果我手动将 get()
换成 toSql()
和 运行 这两个查询,我发现时间相对相似且较小。要明确测量所花费的时间不是 SQL 查询时间;我只是在完成之前和之后立即获取以毫秒为单位的时间,并记录差异。
谁能看出为什么 ->orderBy('view_count', 'DESC')
会增加将近一整秒的代码执行时间,即使 SQL 本身 not/minimally 更慢?
似乎执行原始查询和加水和加载似乎加快了查询速度。这并没有回答为什么 order by 会导致这样的问题,但它确实回答了如何解决手头的问题:
$products = self::hydrate(DB::select(
"select `products`.*, COUNT(product_view_history.id) as view_count
from `products` left join `product_view_history`
on `product_view_history`.`product_id` = `products`.`id`
where `products`.`launch_date` is not null
group by `product_view_history`.`product_id`
order by `view_count` desc, `products`.`id` desc limit {$limit}"))
->load(['owner.images', 'owner.star', 'owner.follows', 'owner.followers', 'company.products.alphas']);
对我来说,这是由于在 where 查询中使用 "wrong" 数据类型造成的。 例如,我按名为 "username" 的列进行过滤,该列是一个 varchar,但插入了一个 Int 作为过滤依据的值。 使用 orderBy 时花费了很长时间,但是当删除 orderBy 时又很快了。 解决方案至少对我来说是将用户名转换为字符串,并且 orderBy 像以前一样流畅。我不知道真正的原因,但可能 Eloquent 在使用不匹配的数据类型时进行不同的转换或排序。