Php Laravel原始查询比Laravel之外的同一查询慢几个数量级
我正在Debian上使用Laravel5.2和PHP7.0.6。MySQL是远程服务器上的5.5.30 当我通过HeidiSQL或从命令行客户端运行查询时,它将在大约0.2秒内执行。在Laravel(调试模式打开或关闭)中执行完全相同的SQL几乎需要500秒。我试着从MySQL查询日志中提取Laravel查询并运行它,结果运行得很快。只有在通过Laravel执行语句时,它才会变慢。laravel代码如下所示。我的计时器代码在这行之前和之后,所以减速肯定在这里。查询只返回一行Php Laravel原始查询比Laravel之外的同一查询慢几个数量级,php,mysql,laravel,eloquent,laravel-5.2,Php,Mysql,Laravel,Eloquent,Laravel 5.2,我正在Debian上使用Laravel5.2和PHP7.0.6。MySQL是远程服务器上的5.5.30 当我通过HeidiSQL或从命令行客户端运行查询时,它将在大约0.2秒内执行。在Laravel(调试模式打开或关闭)中执行完全相同的SQL几乎需要500秒。我试着从MySQL查询日志中提取Laravel查询并运行它,结果运行得很快。只有在通过Laravel执行语句时,它才会变慢。laravel代码如下所示。我的计时器代码在这行之前和之后,所以减速肯定在这里。查询只返回一行 $results =
$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'
选择ll.id,
ll.other_id,
第三名律师,
在,
L.h_id,
法律顾问,
L.sub2,
法律地位,
px.u创建于,
b、 缩写,
ldl.transaction\u id,
低密度脂蛋白。购买价格,
CONCAT(ld.first_name',ld.last_name)作为全名,
lcase(ll.电子邮件地址)作为电子邮件地址,
ll.总收入
表1-11
ll.id=ld.fid上的内部联接表2 ld
内部联接表3 ll.id上的ldl=ldl.fid
ll.id=px.fid上的左外联接表4 px
ldl.bid=b.id上的内部联接表5b
其中,ll.在“2016-05-04 00:00:00”处创建
并于<'2016-05-04 23:59:59'
和v_id IN(41,42,43,45,46)
和(131)中的ldl.b_id
以及‘’中的lcase(ll.email_地址)example@email.com')
和ll.status='ACCEPTED'
我遇到了这个问题,最终找到了解决方案。我有一个查询,当我在命令行上运行时,它在大约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']);
我的问题解决了 对于其他与此相关的问题,我们在查询db视图时遇到了类似的问题,但解决方案与上述相反 直接在数据库中运行此查询时,响应时间仅为几分之一秒:
select * from `db_view` where `id` = 12345;
但当使用fluent builder进行相同查询时,响应时间>12秒(!):
从mysqlshow 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];
显示您的$sql变量。有关此查询的任何内容看起来都不快速。你在那张桌子上的索引是什么样子的?您是否可以使用
BETWEEN
进行created\u的比较?解释
有什么要说的?有可能你在拉威尔内部碰到了某种资源锁。将此查询减少到绝对最小值,以消除诊断中的因素。像从表1中选择ll.id ll LIMIT 1
作为开始。@tadman什么样的资源锁在Laravel中?虽然查询可以优化,但到目前为止的问题似乎是,为什么Laravel(或者反过来是PHP)执行此查询的优化程度低于所述的其他方法。观察到的差异似乎是在使用Laravel的DBAL(Fluent)和任何其他涉及的组件执行时出现的。我很想听听您对框架中什么可能会导致执行查询时0.2s和500s之间的差异的看法。如果在完全相同的数据库上运行的是完全相同的查询(我怀疑不是这样),并且这里唯一的变量是direct query vs.inside Laravel,那么肯定还涉及到其他一些因素。最有可能出现的情况是事务或查询未能运行到完成,并在500秒后超时,从而导致此查询无法执行。您需要在这里进行简化,并提出一个最简单的示例,说明需要花费很长时间才能运行的东西。如果这是选择1
,你必须继续挖掘。@Dave你解决过这个问题吗?我也遇到了同样的问题。IIRC,参数化查询的执行计划可以缓存并重新使用,因此,如果经常使用不同的名称值运行此查询,则上述方法确实会带来潜在的好处。我也有同样的问题,但此解决方案无法解决问题。
DB::select("select * from `db_view` where `id` = {$this->id}")[0];