MySQL 优化简单连接查询 - 内存或 I/O 问题?
Posted
技术标签:
【中文标题】MySQL 优化简单连接查询 - 内存或 I/O 问题?【英文标题】:MySQL Optimizing Simple Join Query - Memory or I/O Issue? 【发布时间】:2020-05-11 17:39:58 【问题描述】:我试图弄清楚为什么我们的生产环境中的查询会花费这么多时间(~20 sec)
。我已经尝试在本地创建数据库并生成相同的数据,并且使用完全相同的查询运行时间不到半秒。
有谁知道是什么导致了这种放缓? 我现在最好的猜测是可能的内存限制导致用于交换到磁盘的索引
查看表格并解释下面的查询:
(.15 sec) SELECT COUNT(*) FROM user;
(.32 sec) SELECT COUNT(*) FROM profile;
(20.80 sec) SELECT COUNT(*) FROM user INNER JOIN profile ON user.id = profile.user_id;
用户表:
| id | guid | status | username | email |
用户索引:
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user | 0 | PRIMARY | 1 | id | A | 355448 | NULL | NULL | | BTREE | | |
| user | 0 | unique_email | 1 | email | A | 2 | NULL | NULL | YES | BTREE | | |
| user | 0 | unique_username | 1 | username | A | 2 | NULL | NULL | YES | BTREE | | |
个人资料表:
| user_id | firstname | lastname | full_name |
个人资料索引:
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+-----------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| profile | 0 | PRIMARY | 1 | user_id | A | 330496 | NULL | NULL | | BTREE | | |
| profile | 1 | idx_profile_full_name | 1 | full_name | A | 2 | NULL | NULL | YES | BTREE | | |
+---------+------------+-----------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
查询说明:
mysql> EXPLAIN SELECT COUNT(*) FROM profile JOIN user ON user.id = profile.user_id;
+----+-------------+---------+--------+---------------+-----------------------+---------+------------------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+--------+---------------+-----------------------+---------+------------------------+--------+-------------+
| 1 | SIMPLE | profile | index | PRIMARY | idx_profile_full_name | 258 | NULL | 330496 | Using index |
| 1 | SIMPLE | user | eq_ref | PRIMARY | PRIMARY | 4 | humhub.profile.user_id | 1 | Using index |
+----+-------------+---------+--------+---------------+-----------------------+---------+------------------------+--------+-------------+
【问题讨论】:
出了点问题。为什么在查询中根本不使用full_name
时会使用idx_profile_full_name
。
请提供SHOW CREATE TABLE
;它比DESCRIBE
更具描述性。
【参考方案1】:
很可能是 MySQL 5.7/8.0 查询计划程序突然脑死亡的 heisenbug。
运行 ANALYZE TABLE user; ANALYZE TABLE profile;
并查看查询计划器是否变得不混乱。
避免重复的唯一方法是使用索引提示:
SELECT COUNT(*) FROM profile USE INDEX (PRIMARY) JOIN user ON user.id = profile.user_id;
【讨论】:
以上是关于MySQL 优化简单连接查询 - 内存或 I/O 问题?的主要内容,如果未能解决你的问题,请参考以下文章