使用内部联接和主键排序的MySQL 5.7查询确实很慢

时间:2019-07-04 08:34:04

标签: mysql sql-order-by inner-join

我正在尝试使此查询正常工作,该查询为对多个标签(又称为酒吧)感兴趣的用户获取供稿。 user和tag的映射在user_pub表中,并且帖子本身具有pub_id。下面的模式。

CREATE TABLE `post` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `pub_id` bigint(20) unsigned NOT NULL,
  `author_id` bigint(20) unsigned NOT NULL,
  `snippet` text COLLATE utf8mb4_unicode_ci,
  `type` tinyint(3) unsigned NOT NULL,
  `status` tinyint(3) unsigned NOT NULL DEFAULT '1',
  `time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `time_idx` (`time`),
  KEY `fk_author_id_idx` (`author_id`),
  KEY `idx_pub_status_type_author` (`pub_id`,`type`,`status`,`author_id`)
) ENGINE=InnoDB AUTO_INCREMENT=299521 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

CREATE TABLE `user_pub` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) unsigned NOT NULL,
  `pub_id` bigint(20) unsigned NOT NULL,
  `join_status` tinyint(4) NOT NULL DEFAULT '1',
  `time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_unq_up_user_pub` (`user_id`,`pub_id`)
) ENGINE=InnoDB AUTO_INCREMENT=227392 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

查询很简单:

SELECT p.*
FROM post p
INNER JOIN user_pub up ON up.pub_id = p.pub_id
WHERE up.user_id = 1234
ORDER BY p.id DESC LIMIT 10;

没有ORDER BY,速度很快(0.5ms),说明看起来还可以:

+----+-------------+-------+----------------------------+----------------------------+---------+-----------------------+------+----------+-------------+
| id | select_type | table | possible_keys              | key                        | key_len | ref                   | rows | filtered | Extra       |
+----+-------------+-------+----------------------------+----------------------------+---------+-----------------------+------+----------+-------------+
|  1 | SIMPLE      | up    | idx_unq_up_user_pub        | idx_unq_up_user_pub        | 8       | const                 |    2 |   100.00 | Using index |
|  1 | SIMPLE      | p     | idx_pub_status_type_author | idx_pub_status_type_author | 8       | thedb.up.pub_id       |   64 |   100.00 | NULL        |
+----+-------------+-------+----------------------------+----------------------------+---------+-----------------------+------+----------+-------------+

使用ORDER BY,大约需要70毫秒,并说明具有使用索引;使用临时;在EXTRA中使用文件排序

+----+-------------+-------+----------------------------+----------------------------+---------+-----------------------+------+----------+----------------------------------------------+
| id | select_type | table | possible_keys              | key                        | key_len | ref                   | rows | filtered | Extra                                        |
+----+-------------+-------+----------------------------+----------------------------+---------+-----------------------+------+----------+----------------------------------------------+
|  1 | SIMPLE      | up    | idx_unq_up_user_pub        | idx_unq_up_user_pub        | 8       | const                 |    2 |   100.00 | Using index; Using temporary; Using filesort |
|  1 | SIMPLE      | p     | idx_pub_status_type_author | idx_pub_status_type_author | 8       | thedb.up.pub_id       |   64 |   100.00 | NULL                                         |
+----+-------------+-------+----------------------------+----------------------------+---------+-----------------------+------+----------+----------------------------------------------+

我尝试像这样重写此查询,但这没有影响:

SELECT p1.* 
FROM post p1,
    (SELECT p.id
        FROM post p, user_pub up
        WHERE up.user_id = 1234 AND up.pub_id = p.pub_id
    ) p2
WHERE p1.id = p2.id
ORDER BY p1.id DESC LIMIT 10;

总结:

  • 我正在通过邮局表的主键进行订购,因此它应该比70ms接近0.5ms。
  • 我不明白为什么在邮编id上按order by时,为什么在user_pub表而不是post表的行中显示temp,filesort等。

表不是很大,每个表大约有25万行。

0 个答案:

没有答案