Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php RESTAPI的Laravel DB查询速度非常慢_Php_Mysql_Laravel_Eloquent_Mariadb - Fatal编程技术网

Php RESTAPI的Laravel DB查询速度非常慢

Php RESTAPI的Laravel DB查询速度非常慢,php,mysql,laravel,eloquent,mariadb,Php,Mysql,Laravel,Eloquent,Mariadb,我正在和拉威尔一起做我的第一步,试着写一个音乐播放列表。该数据库有3个实体/模型: Play <-n-1-> Song <-n-1-> Artist 该数据库拥有约856000部戏剧,33000首歌曲和15000名艺术家 起初,我试着直接使用模型,急切地加载剧本->歌曲->艺术家 return playsource::collection(Play::whereDate('date',$date)->get()); 通过Laravel在RESTAPI上使用此查询需要2

我正在和拉威尔一起做我的第一步,试着写一个音乐播放列表。该数据库有3个实体/模型:

Play <-n-1-> Song <-n-1-> Artist
该数据库拥有约856000部戏剧,33000首歌曲和15000名艺术家

起初,我试着直接使用模型,急切地加载剧本->歌曲->艺术家

return playsource::collection(Play::whereDate('date',$date)->get());
通过Laravel在RESTAPI上使用此查询需要2.6秒。 我想这很慢

如果我正确理解了Laravel,它会对许多DB查询产生影响:

  • 对剧本的一个查询
  • 另一首歌
  • 但对于每一个剧本/歌曲,都需要对其艺术家进行单独的询问(?)
因此,我尝试创建一个连接查询,以便只有一个DB查询:

returndb::table('plays')
->leftJoin('songs'、'plays.song_id'、'='、'songs.id')
->leftJoin('artists'、'songs.artist_id'、'='、'artists.id')
->选择('plays.*'、'songs.*'、'Artisters.*')
->whereDate('plays.date',$date)
->orderByDesc('plays.date')
->get();
这个查询稍微快一点,但仍然很慢:2.2s

直接在数据库上调用等效的SQL查询要快得多:

选择*
从剧本p
在p.song_id=s.id上左连接歌曲s
在s.artist_id=a.id上左键加入艺术家a
其中日期(p.DATE)=“2020-12-30”
按p.date DESC订购;
->0.4s

我是否做错了什么,或者使用Laravel时这是典型的开销

EDIT1:

好的,我找到了
DB::getQueryLog()
(但这不是我要找的)。现在我知道了:使用三个表和链式急切加载只会导致3db查询。我的第一个是最慢的,将近400毫秒。这两个查询每个只需要1-2毫秒

我还发现流明应该比Laravel快。所以我试过了。我的第一个使用模型的查询现在需要1.4s。为输出映射添加JsonResources会添加0.3s->1.7s。在我看来,所有这一切仍在放缓

但我认为这是我在使用现代框架时必须付出的代价。(我2006年的旧播放列表不使用任何框架)

EDIT2: 第一个查询可以通过以下方式显著增强:

  • date
    列上添加索引
  • 不使用函数(
    DATE(`DATE`)
    ->whereDate('DATE',…)
    )进行查询,而是使用
    ->wherebeen('DATE',[$DATE,'23:59:59'])
    现在第一个查询只需要5毫秒(以前是400毫秒)。对于整个流明查询,我是1.3

  • SQL查询只执行您可以通过向app/providers/AppServiceProvider.php文件中添加以下函数来检查Laravel正在向数据库启动的查询:

    public function boot(){
            if(env('APP_DEBUG')) {
                DB::listen(function($query) {
                    File::append(
                        storage_path('/logs/query.log'),
                        $query->sql . ' [' . implode(', ', $query->bindings) . ']' . PHP_EOL
                );
                });
            }
        }
    
    您将在将创建的/storage/logs/query.log文件中找到每个查询的sql代码。
    这有助于我理解和优化查询生成器语句,有时我也会遇到类似的问题。

    尝试在不转换为特殊集合的情况下进行度量。只需
    Play::whereDate('date',$date)->with(['artist','song'])->get()
    让我们看看生成的SQL,以便发现问题。我在查询后添加了一个强制异常以获取Laravels调试屏幕。在“调试”选项卡下,我可以看到之前的查询及其运行时间。使用JOIN查询,生成的查询看起来与我编写的SQL查询几乎相同,只需0.4s。因此,开销来自拉威尔。不是来自生成的查询。