mysql - 添加 ORDER BY 时查找员工最新事件很慢

标签 mysql

我正在 Laravel 中的遗留系统上工作,我正在尝试提取员工已完成的某些特定类型操作的最新操作。

当我不添加 ORDER BY 时,性能良好。添加它后,查询时间将从 130 毫秒缩短到 18 秒。 actions 表中约有 150 万行。

如何解决性能问题?

我尝试通过删除查询的所有其他部分来隔离问题,以便您更容易阅读:

SELECT
    employees.id,
    (
        SELECT DATE_FORMAT(actions.date, '%Y-%m-%d')
        FROM pivot
        JOIN actions
        ON pivot.actions_id = actions.id
        WHERE employees.id = pivot.employee_id
        AND (actions.type = 'meeting'
            OR (actions.type = 'phone_call'
            AND JSON_VALID(actions.data) = 1
            AND actions.data->>'$.update_status' = 1))
        LIMIT 1
    ) AS latest_action
FROM employees
ORDER BY latest_action DESC

我尝试使用 LEFT JOINMAX() 代替,但它似乎没有解决我的问题。

我刚刚添加了一个子查询,因为原来的查询已经非常复杂了。但如果您有其他建议,我会洗耳恭听。

更新

EXPLAIN的结果:

id  select_type         table       partitions  type    possible_keys                       key                 key_len ref                     rows    filtered    Extra
1   PRIMARY             employees   NULL        ALL     NULL                                NULL                NULL    NULL                    15217   10          Using where
2   DEPENDENT SUBQUERY  pivot       NULL        ref     actions_type_index,pivot_type_index pivot_type_index    4       dev.employees.id        104     11.11       Using index condition
2   DEPENDENT SUBQUERY  actions     NULL        eq_ref  PRIMARY,Logs                        PRIMARY             4       dev.pivot.actions_id    1       6.68        Using where

更新2

这是索引。我认为索引 employee_type 对于我的特定查询并不重要,但也许应该重新处理它?<​​/p>

# pivot table
KEY `actions_type_index` (`actions_id`,`employee_type`),
KEY `pivot_type_index` (`employee_id`,`employee_type`)

# actions table
KEY `Logs` (`type`,`id`,`is_log`)
# I tried to add `date` index to `actions` table but the problem remains.
KEY `date_index` (`date`)

最佳答案

首先,您的查询非常不理想。 我会这样重写:

SELECT
    e.id,
    DATE_FORMAT(vMAX(a.date), '%Y-%m-%d') AS latest_action
FROM employees e
LEFT JOIN pivot p ON p.employee_id = e.id
LEFT JOIN actions a ON p.actions_id = a.id AND (a.type = 'meeting'
    OR (a.type = 'phone_call'
    AND JSON_VALID(a.data) = 1
    AND a.data->>'$.update_status' = 1))
GROUP BY e.id
ORDER BY latest_action DESC

显然,p.employee_idp.actions_ida.date 上必须有索引。在 a.type 上也很好。 另外,最好将 a.data->>'$.update_status' 替换为一些带有索引的简单字段。

关于mysql - 添加 ORDER BY 时查找员工最新事件很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59087494/

相关文章:

MySQL 距离下一次日期出现的天数?

php - "private"网站真正需要多少安全性?

php - 如何在sql中选择可能的行

mysql - Galera 集群问题

mysql - AIR 从下载的模式文件创建本地 SQLite 数据库

PHP/MySQL 分页或 jQuery?

mysql - SQL Server Management Studio Express 和 MySQL?

mysql - 如何使用 bash 文本处理命令将一个字符的单词元素转换为两个字符的单词元素?

标记新值和重复值的 Mysql 代码

php - 如何使用 php mysql 以所见即所得的方式显示数据库中的数据?