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

Dav*_*ave 5 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);
Run Code Online (Sandbox Code Playgroud)

查询的匿名版本如下(否则将可见特定于业务的数据)。希望我在这个过程中没有弄乱任何东西。

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'
Run Code Online (Sandbox Code Playgroud)

And*_*rew 3

我经历过这个问题并最终找到了解决方案。我有一个查询,当我在命令行上运行时,它执行了大约 40 毫秒。当我使用以下命令将相同的查询放入 Laravel 时:

DB::select( $myQuery ); // Where $myQuery is the exact string I ran on the command line
Run Code Online (Sandbox Code Playgroud)

...查询花费了大约 1 分钟。显然出了什么问题。

最后,一切都与参数绑定有关。通过简单地改变这个:

DB::select("SELECT * FROM users WHERE username='Andrew'");
Run Code Online (Sandbox Code Playgroud)

...对此:

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

我的问题解决了。

  • IIRC,参数化查询的执行计划可以被缓存和重用,因此如果此查询经常使用不同的“name”值运行,上述方法确实会提供潜在的好处。 (2认同)