mysql - mysql派生表如何使用索引

标签 mysql derived-table

MySQL 版本 5.6.33

我有两个表(文件 & 详细信息)要进行内连接

files,有一个名为 idx_record(record_id) 的索引

details,有一个名为 idx_end_org_record(end_at, org_id, record_id) 的索引

explain
SELECT
    id as file_id,
    record_id,
    recording_path
FROM `files`
INNER JOIN
(
    SELECT `details`.`record_id`
    FROM `details` 
    WHERE `details`.`org_id` IN (6231, 6232, 6233, 6234) 
    AND (`details`.`end_at` BETWEEN '2017-05-31 16:00:00' AND '2017-06-13 16:00:00') 
    ORDER BY end_at desc
) as b
    on `files`.record_id = b.record_id 
WHERE (file_name IS NOT NULL )
LIMIT 30

输出如下

+----+-------------+--------------+-------+--------------------+--------------------+---------+------------------+---------+--------------------------+
| id | select_type | table        | type  | possible_keys      | key                | key_len | ref              | rows    | Extra                    |
+----+-------------+--------------+-------+--------------------+--------------------+---------+------------------+---------+--------------------------+
|  1 | PRIMARY     | <derived2>   | ALL   | NULL               | NULL               | NULL    | NULL             | 3844632 | Using where              |
|  1 | PRIMARY     | files        | ref   | idx_record         | idx_record         | 5       | b.record_id      |       1 | Using where              |
|  2 | DERIVED     | details      | range | idx_end_org_record | idx_end_org_record | 11      | NULL             | 3844632 | Using where; Using index |
+----+-------------+--------------+-------+--------------------+--------------------+---------+------------------+---------+--------------------------+

如您所见,<derived2>表未使用任何索引,使得此查询几乎需要 1 秒才能完成。

感谢任何帮助!


此外,删除 WHERE (file_name IS NOT NULL )在查询中没有任何区别。

而在 mysql 5.7 中,这个问题甚至不存在,但目前我正在尝试在 5.6 中解决这个问题。

最佳答案

我不明白子查询的意义所在。特别是子查询中的ORDER BY是没有意义的。如果您将查询编写为两个表之间的直接连接,那么优化器应该能够利用连接列上的索引:

SELECT
id as file_id,
record_id,
recording_path
FROM files f
INNER JOIN details d
    ON f.record_id = d.record_id AND
       d.org_id IN (6231, 6232, 6233, 6234) AND
       d.end_at BETWEEN '2017-05-31 16:00:00' AND '2017-06-13 16:00:00'
WHERE f.file_name IS NOT NULL
ORDER BY <some column>    -- it doesn't make sense most of the time to use LIMIT
LIMIT 30                  -- without ORDER BY

details 表中的 record_idorg_idend_at 以及 上添加索引files 表中的 >file_name,应该会给您带来一些性能改进。

关于mysql - mysql派生表如何使用索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44690996/

相关文章:

MySQL DELETE 查询派生表

mysql - 我如何告诉 MySQL 优化器使用派生表上的索引?

mysql - VB 应用程序搜索 MySQL 数据库以获取登录凭据

java - mysql + 阿兹卡类 : Reading "LongBlob"

database - SQLite3 数据库中的派生字段

mysql - 在 MySQL 的内部查询中使用外部查询的结果集

php - 从派生表中提取列并将它们汇总到一个 MySQL SELECT 语句中

mysql - sql分组求平均值

php - 准备好的语句不填充数据库

mysql - 复杂的SQL更新语句