mysql - 查询使用没有强制索引的临时表
问题描述
询问
SELECT SQL_NO_CACHE contacts.id,
contacts.date_modified contacts__date_modified
FROM contacts
INNER JOIN
(SELECT tst.team_set_id
FROM team_sets_teams tst
INNER JOIN team_memberships team_membershipscontacts ON (team_membershipscontacts.team_id = tst.team_id)
AND (team_membershipscontacts.user_id = '5daa2e92-c347-11e9-afc5-525400a80916')
AND (team_membershipscontacts.deleted = 0)
GROUP BY tst.team_set_id) contacts_tf ON contacts_tf.team_set_id = contacts.team_set_id
LEFT JOIN contacts_cstm contacts_cstm ON contacts_cstm.id_c = contacts.id
WHERE contacts.deleted = 0
ORDER BY contacts.date_modified DESC,
contacts.id DESC
LIMIT 21;
耗时极长(2M 条记录需要 2 分钟)。我无法更改此查询,因为它是系统生成的
这是它的解释:
+----+-------------+--------------------------+------------+--------+-------------------------------------------------------------------------------------------------------+----------------------------+---------+-------------------------------------------+---------+----------+---------------------------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------------------+------------+--------+-------------------------------------------------------------------------------------------------------+----------------------------+---------+-------------------------------------------+---------+----------+---------------------------------------------------------------------+
| 1 | PRIMARY | contacts | NULL | ref | idx_contacts_tmst_id,idx_del_date_modified,idx_contacts_del_last,idx_cont_del_reports,idx_del_id_user | idx_del_date_modified | 2 | const | 1113718 | 100.00 | Using temporary; Using filesort |
| 1 | PRIMARY | <derived3> | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50.00 | Using where; Using join buffer (Block Nested Loop) |
| 1 | PRIMARY | contacts_cstm | NULL | eq_ref | PRIMARY | PRIMARY | 144 | sugarcrm.contacts.id | 1 | 100.00 | Using index |
| 3 | DERIVED | team_membershipscontacts | NULL | ref | idx_team_membership,idx_teammemb_team_user,idx_del_team_user | idx_team_membership | 145 | const | 2 | 99.36 | Using index condition; Using where; Using temporary; Using filesort |
| 3 | DERIVED | tst | NULL | ref | idx_ud_set_id,idx_ud_team_id,idx_ud_team_set_id,idx_ud_team_id_team_set_id | idx_ud_team_id_team_set_id | 144 | sugarcrm.team_membershipscontacts.team_id | 1 | 100.00 | Using index |
+----+-------------+--------------------------+------------+--------+-------------------------------------------------------------------------------------------------------+----------------------------+---------+-------------------------------------------+---------+----------+---------------------------------------------------------------------+
但是当我使用force index(idx_del_date_modified)
(与解释中使用的索引相同)时,查询只需要 0.01 秒,我得到的解释略有不同。
+----+-------------+--------------------------+------------+--------+----------------------------------------------------------------------------+----------------------------+---------+-------------------------------------------+---------+----------+---------------------------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------------------+------------+--------+----------------------------------------------------------------------------+----------------------------+---------+-------------------------------------------+---------+----------+---------------------------------------------------------------------+
| 1 | PRIMARY | contacts | NULL | ref | idx_del_date_modified | idx_del_date_modified | 2 | const | 1113718 | 100.00 | Using where |
| 1 | PRIMARY | <derived2> | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50.00 | Using where |
| 1 | PRIMARY | contacts_cstm | NULL | eq_ref | PRIMARY | PRIMARY | 144 | sugarcrm.contacts.id | 1 | 100.00 | Using index |
| 2 | DERIVED | team_membershipscontacts | NULL | ref | idx_team_membership,idx_teammemb_team_user,idx_del_team_user | idx_team_membership | 145 | const | 2 | 99.36 | Using index condition; Using where; Using temporary; Using filesort |
| 2 | DERIVED | tst | NULL | ref | idx_ud_set_id,idx_ud_team_id,idx_ud_team_set_id,idx_ud_team_id_team_set_id | idx_ud_team_id_team_set_id | 144 | sugarcrm.team_membershipscontacts.team_id | 1 | 100.00 | Using index |
+----+-------------+--------------------------+------------+--------+----------------------------------------------------------------------------+----------------------------+---------+-------------------------------------------+---------+----------+---------------------------------------------------------------------+
第一个查询使用临时表和文件排序,但查询force index
只使用 where。查询不应该相同吗?为什么使用强制索引的查询要快得多 - 使用的索引仍然是一样的。
解决方案
根据 MySQL 手册:
可以在以下条件下创建临时表:
如果存在 ORDER BY 子句和不同的 GROUP BY 子句,或者如果 ORDER BY 或 GROUP BY 包含来自连接队列中第一个表以外的表的列,则会创建一个临时表。
DISTINCT 与 ORDER BY 结合可能需要一个临时表。
如果使用 SQL_SMALL_RESULT 选项,MySQL 将使用内存中的临时表,除非查询还包含需要磁盘存储的元素(稍后描述)。
很可能,您有更好的性能,因为在 MySQL 中有查询优化器组件。
如果创建索引,即使索引存在,查询优化器也无法使用索引列。使用force index(..)
你强制 MySql 使用索引,而不是。
请在此处考虑一个详细的示例。
推荐阅读
- javascript - 从模块导入多个条目并分配给 JavaScript 中的某个别名
- r - R - 返回找到第一个给定值的行的列名
- python - 无法在兄弟子文件夹之间导入 python 文件
- java - QueryDSL 和枚举内部字段持续存在
- java - log4j2 - 需要帮助设置 JMS Appender 以使用 IBM MQ 系列
- c# - 如何在 EF Core 中创建外键关系?
- ios - Ionic Xcode 无法打开文件(目标应用程序)
- reactjs - 如何在 React 中访问组件之外的 Redux 存储
- javascript - 在特定的反应地图项上应用样式
- c++ - C++ atomics:如何只允许一个线程访问一个函数?