Laravel/MySQL:查询运行时间非常长

qmelpv7a  于 2023-02-28  发布在  Mysql
关注(0)|答案(2)|浏览(151)

在我的laravel项目中,我正在用数据库种子做一些测试,以检查许多数据库条目的性能。在我的项目中,我有一个模型FlightView,通过protected $table = 'view_flights';使用SQL视图作为数据库。
在测试过程中,我意识到像FlightView::where('aircraft_id',1)->get()这样的查询变得非常慢(每次调用2或2.5秒),我正在用Laravel Debugbar评估laravel中的查询运行时。
我意识到,在过滤一个飞机ID时,底层查询的处理方式不同(运行时间2到2.5秒),但是当过滤两个或多个飞行器id时非常快(运行时间大约100毫秒)。通过检查底层视图查询,我做了一些优化,将LEFT JOIN替换为INNER JOIN,以便在两种情况下都使用“ref”(索引查找)(as described here)。
更新视图后,SQL编辑器中的运行时间变为50到100毫秒。然而,在laravel中,使用完全相同的查询仍然非常长:

FlightView::where('aircraft_id',1)->get()
Runtime: 2.23 sec
Query: select * from `view_flights` where `aircraft_id` = 1

我尝试了很多变化,你可以在下面的结果中看到,但我没有得到一个线索是什么出了问题,或者我可以做什么下一步...

FlightView::whereIn('aircraft_id',[1])->get()
Runtime: 2.24 sec
Query: select * from `view_flights` where `aircraft_id` in (1)

为了排除任何雄辩的问题,我尝试了同样的DB外观,但它仍然很慢。

DB::table('view_flights')->where('aircraft_id',1)->get()
Runtime: 2.22 sec
Query: select * from `view_flights` where `aircraft_id` = 1

接下来我尝试了DB::select()语句,但也没有改进:

DB::select('select * from view_flights where aircraft_id=?',[1]);
Runtime: 2.22 sec
Query: select * from `view_flights` where `aircraft_id` = 1

如果没有绑定,查询速度会大大提高:接下来我尝试了DB::select()语句,但也没有改进:

DB::select('select * from view_flights where aircraft_id=1');
Runtime: 23 ms
Query: select * from view_flights where aircraft_id = 1

令人惊讶的是,当过滤两个飞机id时,laravel查询仍然非常快:

FlightView::whereIn('aircraft_id',[1,2])->get()
Runtime: 53 ms
Query: select * from `view_flights` where `aircraft_id` in (1,2)

接下来,我让拉拉威尔试着解释一下,为什么它这么慢:

DB::select('explain select * from view_flights where aircraft_id=?',[1]);
Runtime: 2.22 sec
Query: explain select * from `view_flights` where `aircraft_id` = 1

因此Laravel似乎仍然采用“慢”查询方法,而不是“ref”(索引查找)方法:-(
推测/开放性问题?

  • 这个问题是laravel特有的还是SQL特有的?
  • 是否有任何MySQL设置,这可能会导致不同的行为?
  • 可能是什么原因,laravel处理的查询与我的sql编辑器不同?
  • 是否有相同类型的“SQL视图”-缓存或在Laravel中,可能仍然使用旧版本的视图?
  • laravel内部有没有什么“魔法”可以解释这种行为?
  • 接下来我该怎么办?
8dtrkrch

8dtrkrch1#

我会给予你一些建议。
我希望它能帮助你解决优化问题。

  • 正如他们在评论中所说的,确保在“aircraft_id”列上有一个索引。
  • 仅选择必要的列。
  • 调整Mysql性能:有时问题出在数据库端,可以通过性能调优来提高性能,尤其是110,000条记录并不是一个大数字。
izj3ouym

izj3ouym2#

aircraft_id的数据类型是什么?如果是VARCHAR,那么问题出在对一个数字进行测试上。将1更改为"1"。这样,它会在测试前将每行的aircraft_id转换为字符串。
(That建议也适用于您的IN等。)
而且,确实有INDEX(aircraft_id)

相关问题