gpt4 book ai didi

php - 使用 whereHas 方法的 Laravel Eloquent 查询的奇怪行为

转载 作者:行者123 更新时间:2023-11-29 23:08:32 26 4
gpt4 key购买 nike

我无法弄清楚我的 Laravel 脚本发生了什么。我只是选择一个对象,然后调用它的方法来运行其他查询,但我看到的行为非常不一致。代码如下:

$product = Product::find(1);

echo $product->numberOfOrders('2014-05-22', '2015-01-27');

以下是 numberOfOrders 方法的代码:

public function numberOfOrders($startDate = NULL, $endDate = NULL)
{
if(is_null($startDate)) $startDate = '0000-00-00 00:00:00';
if(is_null($endDate)) $endDate = date("Y-m-d");

return Order::whereHas('orderProducts', function($query)
{
$query->where('product_id', $this->id);

})->whereHas('status', function($query)
{
$query->where('sales_data', 1);

})->where('ext_created_at', '>=', $startDate)->where('ext_created_at', '<=', $endDate.' 23:59:59')->distinct()->count();
}

当此代码运行时,它会挂起大约 10 秒,然后返回整数结果。然后,如果我再次运行相同的代码,它会立即返回结果,并且每次运行时都会继续这样做。如果我更改 $startDate,并再次运行代码,它会挂起 10 秒,然后返回结果。然后,重新运行代码将再次立即返回结果。

其他时候,当代码挂起时,我不会返回结果,而是收到一条错误消息:

PHP Fatal error:  Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 2027 Malformed packet' in /var/www/html/app/vendor/laravel/framework/src/Illuminate/Database/Connection.php:299

出现错误消息后,如果我再次运行代码,结果会立即返回。

我很困惑什么会导致我的代码出现这种不一致。我没有对缓存做任何事情。

我注意到 whereHas 方法实际上向查询添加了子查询,而不是使用连接,我觉得这很奇怪。使用 Datamapper ORM 在 CodeIgniter 中编写类似的代码会向查询添加联接而不是子查询,从而产生更好的性能。子查询会导致问题吗?如果是这样,我仍然不确定为什么事情会表现得如此不一致。

我捕获了一些显示问题发生的数据。这是第一次时 DB::getQueryLog() 的输出:

[3] => Array
(
[query] => select count(*) as aggregate from `orders` where `orders`.`deleted_at` is null and (select count(*) from `order_products` where `order_products`.`order_id` = `orders`.`id` and `product_id` = ? and `order_products`.`deleted_at` is null) >= 1 and (select count(*) from `order_statuses` where `orders`.`order_status_id` = `order_statuses`.`id` and `sales_data` = ? and `order_statuses`.`deleted_at` is null) >= 1 and `ext_created_at` >= ? and `ext_created_at` <= ?
[bindings] => Array
(
[0] => 1
[1] => 1
[2] => 2014-07-29
[3] => 2015-01-27 23:59:59
)

[time] => 22391.73
)

如您所见,运行时间很长。完成后,我再次运行相同的操作,这是输出:

[3] => Array
(
[query] => select count(*) as aggregate from `orders` where `orders`.`deleted_at` is null and (select count(*) from `order_products` where `order_products`.`order_id` = `orders`.`id` and `product_id` = ? and `order_products`.`deleted_at` is null) >= 1 and (select count(*) from `order_statuses` where `orders`.`order_status_id` = `order_statuses`.`id` and `sales_data` = ? and `order_statuses`.`deleted_at` is null) >= 1 and `ext_created_at` >= ? and `ext_created_at` <= ?
[bindings] => Array
(
[0] => 1
[1] => 1
[2] => 2014-07-29
[3] => 2015-01-27 23:59:59
)

[time] => 22391.73
)

[4] => Array
(
[query] => select count(*) as aggregate from `orders` where `orders`.`deleted_at` is null and (select count(*) from `order_products` where `order_products`.`order_id` = `orders`.`id` and `product_id` = ? and `order_products`.`deleted_at` is null) >= 1 and (select count(*) from `order_statuses` where `orders`.`order_status_id` = `order_statuses`.`id` and `sales_data` = ? and `order_statuses`.`deleted_at` is null) >= 1 and `ext_created_at` >= ? and `ext_created_at` <= ?
[bindings] => Array
(
[0] => 1
[1] => 1
[2] => 2014-07-29
[3] => 2015-01-27 23:59:59
)

[time] => 1.81
)

正如您所看到的,完全相同的查询,但速度要快得多。为什么会有这样的差异呢?结果是否缓存在某处?

如果有帮助的话,我正在使用 php artisantinker 运行所有这些代码。

编辑经过更多研究后,我了解到这可能是 mysql query cache 的行为.

最佳答案

您的查询速度非常慢。确保您的表已正确建立索引。

此外,如果查询经常运行,请缓存它们。

Eloquent 有一个漂亮的 remember() 方法。

它将使用您当前的缓存驱动程序来存储查询的结果。到目前为止,Redis 为我做得非常出色。

关于php - 使用 whereHas 方法的 Laravel Eloquent 查询的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28183760/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com