两个索引良好的表的单个INNER JOIN运行时间超过一分钟

时间:2017-12-21 17:16:16

标签: mysql indexing inner-join query-performance

我有一个查询大约需要90秒才能运行,即使这些表应该有正确的索引。我不明白为什么。

我使用的是MySQL,表格是InnoDB。

这是查询:

SELECT count(*)
FROM `following_lists` fl INNER JOIN users u 
ON fl.user_uuid = u.user_uuid
WHERE fl.following_query_id = 1000010 AND u.status <= 2

我希望此查询从表following_lists开始,根据WHERE条件获取4K记录,通过其主键将这些记录连接到表users,检查字段的值在users表中,并返回结果记录的计数。为什么需要这么长时间?可能是因为我加入表格的两个字段是CHAR(40)而不是整数?

这些是涉及的表及其索引:

CREATE TABLE `users` ( 
  `user_uuid` CHAR(40) NOT NULL, 
  `status` TINYINT UNSIGNED NOT NULL, 
  ...

  PRIMARY KEY (`user_uuid`), 
  ...
)

CREATE TABLE `following_lists` ( 
  `following_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `following_query_id` INT UNSIGNED NOT NULL,
  `user_uuid` CHAR(40) NOT NULL,

  PRIMARY KEY (`following_id`), 
  KEY `query_id` (`following_query_id`),
  KEY `user_uuid` (`user_uuid`)
)

这是解释查询的输出:

+----+-------------+-------+--------+--------------------+----------+---------+--------------+------+-------------+
| id | select_type | table |  type  |   possible_keys    |   key    | key_len |     ref      | rows |    Extra    |
+----+-------------+-------+--------+--------------------+----------+---------+--------------+------+-------------+
|  1 | SIMPLE      | fl    | ref    | query_id,user_uuid | query_id |       4 | const        | 3718 |             |
|  1 | SIMPLE      | u     | eq_ref | PRIMARY            | PRIMARY  |     160 | fl.user_uuid |    1 | Using index |
+----+-------------+-------+--------+--------------------+----------+---------+--------------+------+-------------+

进一步详情:

  • following_lists有大约25,000行,但只有3718行fl.following_query_id = 1000010

  • users有大约160k行,但在连接中只应选择3718。只有40条记录符合fl.following_query_id = 1000010 AND u.status <= 2条件。

  • 即使我删除条件AND u.status <= 2,查询仍然很慢。

1 个答案:

答案 0 :(得分:0)

&#34;拥有正确的索引&#34; - 死了。

如果您使用的是MyISAM,请不要这样做。相反,切换到InnoDB。

你需要following_lists.id吗? (following_query_id, user_uuid)是唯一的吗?如果是,请将它们设为PRIMARY KEY

如果您无法执行上述操作,请更改

KEY `query_id` (`following_query_id`)

INDEX(following_query_id, user_uuid)

UUIDs效率很低,尤其是在不必要地声明utf8mb4CHAR且大小超过必要时。更改为CHAR(36) CHARACTER SET ascii。 (请注意&`34; 160&#34;在`EXPLAIN显着缩小。)

更多关于UUID对性能有害的原因:http://mysql.rjweb.org/doc.php/uuid

你有多少内存? innodb_buffer_pool_size的设置是什么? (听起来太低了。)

有关索引的更多信息:http://mysql.rjweb.org/doc.php/index_cookbook_mysql