2017-10-17 123 views
4

我想申请where条件关系。这是我做的:差在哪里Laravel性能

Replay::whereHas('players', function ($query) { 
    $query->where('battletag_name', 'test'); 
})->limit(100); 

生成下面的查询:

select * from `replays` 
where exists (
    select * from `players` 
    where `replays`.`id` = `players`.`replay_id` 
     and `battletag_name` = 'test') 
order by `id` asc 
limit 100; 

其中在70秒执行。如果我手动重写这样的查询:

select * from `replays` 
where id in (
    select replay_id from `players` 
    where `battletag_name` = 'test') 
order by `id` asc 
limit 100; 

它在0.4秒内执行。为什么where exists是默认行为,如果它太慢?有没有办法使用查询生成器生成正确的where in查询,还是需要注入原始SQL?也许我完全搞错了什么?

replays表有4M行,players有40M行,所有相关列都被索引,数据集不适合MySQL服务器内存。

更新:发现正确的查询可以产生如下:

Replay::whereIn('id', function ($query) { 
    $query->select('replay_id')->from('players')->where('battletag_name', 'test'); 
})->limit(100); 

还有一个问题,为什么exists表现这么糟糕,为什么它是默认的行为

+0

更快的查询我建议不要选择* ..尝试选择特定的属性而不是全部。 – parkway

+0

我需要为我的情况选择所有这些。即使只选择“id”列,查询性能也会提高不到1%,因此可以忽略不计。 – Poma

回答

1

我觉得表现不取决于在哪里只有它取决于你选择了多少记录

再加上试图优化你的mysql服务器

https://dev.mysql.com/doc/refman/5.7/en/optimize-overview.html

,同时优化你的PHP服务器

,如果你有你为什么不使用原始查询对象从幼虫

$replay = DB::select('select * from replays where id in (
select replay_id from players where battletag_name = ?) 
order by id asc limit 100', ['test'] 
); 
+0

这两个查询都会因为“limit”子句而精确选择100行。哪里有70秒,哪里有0.4秒。优化与问题无关,因为它们将减少查询执行时间。 – Poma

+0

然后,也许你可以使用上面提到的原始查询 –

+0

真实应用程序中的查询比有很多条件的查询更复杂,我真的需要查询生成器。从大量的原始字符串部分构建它将使我的代码变成意大利面条。 – Poma