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 问题?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL优化思路,以及解决方案

mysql优化

mysql性能优化

如何最简单的优化MySql

MySQL优化系列之一

mysql-索引与优化