laravel 中的慢查询

Posted

技术标签:

【中文标题】laravel 中的慢查询【英文标题】:Slow query in laravel 【发布时间】:2020-01-16 13:41:22 【问题描述】:

我有一个 laravel 应用程序,但是一个查询需要很长时间才能执行。

我尝试构建原始查询但没有成功。

查询是这个:

$utente = Utente::with('coll')->with('collaboratori')
            ->where('id', '<>', '0')
            ->whereHas('coll', function ($query) use($id_utente, $att_dummy)
                $query->where('collaboratori_id', 'like', $id_utente);)
            ->orderBy('created_at')
            ->get();

我还尝试使用 queryLog 查看 sql 查询,laravel 执行了不同的查询:


select * from `utenti_nuovo` where `id` <> 0 and exists (select * from `collaboratori_utenti` where `utenti_nuovo`.`id` = `collaboratori_utenti`.`id_utente` 
and `collaboratori_id` like 100008) order by `created_at` asc

select * from `collaboratori_utenti` where `collaboratori_utenti`.`id_utente` in (718, 834, 844, 848, 875, 890, 894, 895, 897, 898)

select * from `collaboratori` where `collaboratori`.`id` in (12,13,16)

select `collaboratori`.*, `collaboratori_utenti`.`id_utente` as `pivot_id_utente`, `collaboratori_utenti`.`collaboratori_id` as `pivot_collaboratori_id`, 
`collaboratori_utenti`.`attivita` as `pivot_attivita`, `collaboratori_utenti`.`created_at` as `pivot_created_at`, `collaboratori_utenti`.`updated_at` as `pivot_updated_at` 
from `collaboratori` inner join `collaboratori_utenti` on `collaboratori`.`id` = `collaboratori_utenti`.`collaboratori_id` 
where `collaboratori_utenti`.`id_utente` in (718, 834, 844, 848, 875, 890, 894, 895, 897, 898)

这些查询中的第一个是导致很长时间等待的慢查询。

有没有办法通过更快的查询来更改 EXIST?

【问题讨论】:

我认为加入会更有效率... 尝试将 ` 'like', $id_utente` 更改为 ` '=', $id_utente` 你为什么用like而不是=? 使用like会避免mysql使用索引。另外,你的 colaboratori_id 上有索引吗?波那血清! 每张表有多少行? 【参考方案1】:

仅选择您需要的字段。这将减少加载时间。

【讨论】:

不会对查询速度造成太大影响。【参考方案2】:

为了优化查询时间,可以使用laravel cursors。不要以-&gt;get() 结束查询,只需使用-&gt;cursor(),如下所示:

$utente = Utente::with('coll')->with('collaboratori')
    ->where('id', '<>', '0')
    ->whereHas('coll', function ($query) use($id_utente, $att_dummy)
        $query->where('collaboratori_id', 'like', $id_utente);)
    ->orderBy('created_at')
    ->cursor();

使用大型数据库时,最好使用cursor。下面是使用get、chunk和cursor的对比,from this answer:

10,000 条记录:

+-------------+-----------+------------+
|             | Time(sec) | Memory(MB) |
+-------------+-----------+------------+
| get()       |      0.17 |         22 |
| chunk(100)  |      0.38 |         10 |
| chunk(1000) |      0.17 |         12 |
| cursor()    |      0.16 |         14 |
+-------------+-----------+------------+

100,000 条记录:

+--------------+------------+------------+
|              | Time(sec)  | Memory(MB) |
+--------------+------------+------------+
| get()        |        0.8 |     132    |
| chunk(100)   |       19.9 |      10    |
| chunk(1000)  |        2.3 |      12    |
| chunk(10000) |        1.1 |      34    |
| cursor()     |        0.5 |      45    |
+--------------+------------+------------+

【讨论】:

以上是关于laravel 中的慢查询的主要内容,如果未能解决你的问题,请参考以下文章

Django 慢查询:将 django 过滤语句连接到数据库日志中的慢查询

phpMyAdmin中的慢查询但Mysql慢查询日志文件中没有[关闭]

查询中的慢排序

Postgres 中的慢查询优化

优化 WordPress 插件“更好的 WordPress 最近评论”中的慢查询

死磕 Redis----- 如何排查 Redis 中的慢查询