差在哪里有Laravel的表现

Pom*_*oma 14 php mysql laravel mysql-5.7 laravel-5.5

我想where对关系应用条件.这是我做的:

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

它生成以下查询:

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

在70秒内执行.如果我手动重写这样的查询:

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

它在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);
Run Code Online (Sandbox Code Playgroud)

仍然有一个问题,为什么exists表现如此糟糕,为什么它是默认行为

Ric*_*ano 5

whereHas 在没有索引的表上性能很差,在上面加上索引就可以了!

    Schema::table('category_product', function (Blueprint $table) {
        $table->index(['category_id', 'product_id']);
    });
Run Code Online (Sandbox Code Playgroud)


小智 0

我认为性能不取决于whereHas只取决于你选择了多少条记录

另外尝试优化你的mysql服务器

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

并优化您的 php 服务器

如果您有更快的查询,为什么不使用 larval 的原始查询对象

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

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