Laravel RAW查询比Laravel之外的同一查询慢几个数量级

时间:2016-06-01 16:17:52

标签: php mysql laravel eloquent laravel-5.2

我在Debian上使用Laravel 5.2和PHP 7.0.6。 MySQL在远程服务器上是5.5.30。

当我通过HeidiSQL或命令行客户端运行查询时,它会在大约0.2秒内执行。在Laravel中执行完全相同的SQL(打开或关闭调试模式)需要将近500秒。我尝试将Laravel查询从MySQL查询日志中拉出并运行它,并且运行速度很快。只有在通过Laravel执行声明时它才会变慢。 laravel代码如下。我的计时器代码在此行之前和之后,因此减速肯定在这里。查询只返回一行。

$results = \DB::select($sql);

下面是查询的匿名版本(否则将显示特定于业务的数据)。希望我在这个过程中没有任何损失。

SELECT  ll.id,
    ll.other_id,
    ll.third_id,
    ll.created_at,
    ll.h_id,
    ll.sub,
    ll.sub2,
    ll.status,
    px.created_at,
    b.abbr,
    ldl.transaction_id,
    ldl.purchase_price,
    CONCAT(ld.first_name, ' ', ld.last_name) as fullname,
    lcase(ll.email_address) as email_address,
    ll.total_revenue

FROM    table1 ll
INNER JOIN table2 ld on ll.id = ld.fid
INNER JOIN table3 ldl on ll.id = ldl.fid
LEFT OUTER JOIN table4 px on ll.id = px.fid
INNER JOIN table5 b on ldl.bid = b.id

WHERE ll.created_at > '2016-05-04 00:00:00'
AND ll.created_at < '2016-05-04 23:59:59'
AND v_id IN (41,42,43,45,46)
AND ldl.b_id IN (131)
AND lcase(ll.email_address) in ('example@email.com')
AND ll.status = 'ACCEPTED'

2 个答案:

答案 0 :(得分:2)

我遇到了这个问题,终于找到了解决方案。我有一个查询,当我在命令行上运行时,它在40毫秒内执行。当我使用以下相同的确切查询到Laravel中时:

DB::select( $myQuery ); // Where $myQuery is the exact string I ran on the command line

...查询耗时约1分钟。明显有问题。

最后,它与参数绑定有关。只需更改以下内容即可:

DB::select("SELECT * FROM users WHERE username='Andrew'");

...对此:

DB::select("SELECT * FROM users WHERE username = :name",['name' => 'Andrew']);

我的问题解决了。

答案 1 :(得分:2)

对于其他为此苦苦挣扎的人,在查询数据库 view 时遇到了类似的问题,但解决方案与上述相反。

直接在数据库中运行此查询时,响应时间仅为几分之一秒。:

select * from `db_view` where `id` = 12345;

但是当对同一查询使用流利的生成器时,响应时间大于12秒(!):

DB::table('db_view')->where('id', $this->id)->first();

从mysql show full processlist看来,每次调用查询时db都会创建排序索引,但出于某种原因,只有在从Laravel调用时,数据库才创建排序索引。

根据上面的答案,我们尝试了此操作,但还是没有帮助:

DB::select("select * from `db_view` where `id` = :id", ['id' => $this->id])[0];

最后,我们尝试完全排除绑定,并且最终按预期工作,而没有为每个查询建立排序索引:

DB::select("select * from `db_view` where `id` = {$this->id}")[0];