MySQL 查询优化 - 现有查询运行速度太慢

标签 mysql sql

我正在尝试优化以下查询,但它对我来说运行速度非常慢:

SELECT `trans_email`.*
, `email_statuses`.`recipient`, `email_statuses`.`status_id`, `email_statuses`.`message`, `email_statuses`.`status_received_at`
, `trans`.`doc`
FROM `trans_email`
LEFT JOIN `email_statuses` ON `trans_email`.`id` = `email_statuses`.`trans_email_id`
LEFT JOIN `trans` ON `trans_email`.`trans_id` = `trans`.`id`
WHERE `trans_email`.`type_id` = 0 AND `trans`.`company_id` = 1 
ORDER BY `email_statuses`.`status_received_at` DESC
LIMIT 25 OFFSET 0

25 rows in set (4.87 sec)

这是EXPLAIN的输出: 编号:1 选择类型:简单 表:trans_email 分区:NULL 类型:全部 可能的键:trans_id 键:空 key_len: NULL 引用:空 行:769970 过滤:10.00 额外:使用地点;使用临时的;使用文件排序 ************************** 2. 行 ****************** ****** 编号:1 选择类型:简单 表:反式 分区:NULL 类型:eq_ref 可能的键:主、fk_trans_company、co_del_drft_type、co_drft_del_utc 关键:主要 key 长度:4 引用:trans_email.trans_id 行数:1 过滤:5.00 额外:使用地点 ************************** 3. 行 ****************** ****** 编号:1 选择类型:简单 表:电子邮件状态 分区:NULL 类型:引用 possible_keys: email_statuses_trans_email_id_foreign 键:email_statuses_trans_email_id_foreign key 长度:4 引用:trans_email.id 行数:2 过滤:100.00 额外:空 3 行一组,1 次警告(0.00 秒)

据我所知,所有内容都已正确索引。 (请注意,trans_email.type_id 实际上是一个 bool 值,因此尚未编入索引。)

最佳答案

尽管您在 WHERE 的连接表中需要非 NULL 字段,但您仍使用 LEFT JOIN。

如果 LEFT JOIN 为 trans 生成 NULL 行,则

`trans`.`company_id` = 1 不能为 true,因此 LEFT JOIN 不会生成任何额外行(与内部 JOIN 相比)将在最终结果中被接受。

使用 LEFT JOIN,您至少会生成 769970 行(即 trans_email 中的每行至少一行),然后将它们削减到 25。如果您有一个内部 JOIN,您将立即从主索引中减少到 50 行(假设 bool 列分布大致相等),然后根据 bool 条件减少到 25 行。

编辑:更改另一个 LEFT JOIN(email_statuses 之一)实际上会更改您的结果,除非您在 email_statuses 表中完全覆盖,并且它不应该一旦另一个 LEFT JOIN 消失,确实会影响您的运行时,所以请随意保留该 LEFT JOIN 原样。

因此 - 试试这个(只有一个词更 slim ):

SELECT `trans_email`.*
, `email_statuses`.`recipient`, `email_statuses`.`status_id`, `email_statuses`.`message`, `email_statuses`.`status_received_at`
, `trans`.`doc`
FROM `trans_email`
JOIN `email_statuses` ON `trans_email`.`id` = `email_statuses`.`trans_email_id`
LEFT JOIN `trans` ON `trans_email`.`trans_id` = `trans`.`id`
WHERE `trans_email`.`type_id` = 0 AND `trans`.`company_id` = 1 
ORDER BY `email_statuses`.`status_received_at` DESC
LIMIT 25 OFFSET 0

关于MySQL 查询优化 - 现有查询运行速度太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52965734/

相关文章:

php - 将图像附件添加到 PHP 消息?

mysql - SQL 多重连接与计数

PHP/MySQL - 搜索查询

mysql - Codeigniter 如何从模型中的同一列返回多行

sql - 在 ASP 3.0(经典)上捕获 SQL 错误并返回特定的 HttpStatus

sql - 从 SQL Server 2012 查询结果中减去小时数

mysql - 在引用的表中找不到索引,其中引用的列显示为第一列

sql - 如何在以列名为参数的 SELECT 语句中调用用户定义的函数?

sql - 我如何从 PostgreSQL 获取特定日期的特定数据?

mysql - 无法将列数据从 MySQL 中的一个表复制到另一个表