繁体   English   中英

在中等sql中,mysql 5.7比mysql 5.6慢得多

[英]mysql 5.7 is much slower than mysql 5.6 in medium sql

我们正在升级到mysql 5.7,只是发现它比5.6计数器要慢得多。 虽然两者的配置几乎相同,但5.6版本以毫秒为单位执行大多数sql,而对于中等复杂的sql(例如下面的sql),另一个版本大约需要1秒钟或更长时间。

-- Getting most recent users that are email-verified and not banned 

SELECT
    `u`.*
FROM
    `user` AS `u`
INNER JOIN `user` user_table_alias ON user_table_alias.`id` = `u`.`id`
LEFT JOIN `user_suspend` user_suspend_table_alias ON user_suspend_table_alias.`userId` = `user_table_alias`.`id`
WHERE
    (
        `user_suspend_table_alias`.`id` IS NULL
    )
AND 
    `user_table_alias`.`emailVerify` = 1

ORDER BY
    `u`.`joinStamp` DESC
LIMIT 1, 18

这两个表都非常简单并且索引良好:

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(128) NOT NULL DEFAULT '',
  `username` varchar(32) NOT NULL DEFAULT '',
  `password` varchar(64) NOT NULL DEFAULT '',
  `joinStamp` int(11) NOT NULL DEFAULT '0',
  `activityStamp` int(11) NOT NULL DEFAULT '0',
  `accountType` varchar(32) NOT NULL DEFAULT '',
  `emailVerify` tinyint(2) NOT NULL DEFAULT '0',
  `joinIp` int(11) unsigned NOT NULL,
  `locationId` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`),
  UNIQUE KEY `username` (`username`),
  KEY `accountType` (`accountType`),
  KEY `joinStamp` (`joinStamp`),
  KEY `activityStamp` (`activityStamp`)
) ENGINE=MyISAM AUTO_INCREMENT=89747 DEFAULT CHARSET=utf8 COMMENT='utf8_general_ci';

-- ----------------------------
-- Table structure for user_suspend
-- ----------------------------
DROP TABLE IF EXISTS `user_suspend`;
CREATE TABLE `user_suspend` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userId` int(11) DEFAULT NULL,
  `timestamp` int(11) DEFAULT NULL,
  `message` text NOT NULL,
  `expire` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `userId` (`userId`)
) ENGINE=MyISAM AUTO_INCREMENT=513 DEFAULT CHARSET=utf8;

这些表分别具有约100K和1K行。 我注意到了两个我想“修复”的有趣行为:

  1. 删除ORDER BY可使执行时间从〜1.2秒变为0.0015秒!
  2. mysql 5.7未缓存SQL

注意:我们有缓存查询:

显示状态,例如“ Qcache%”

Qcache_free_blocks  19408
Qcache_free_memory  61782816
Qcache_hits 31437169
Qcache_inserts  2406719
Qcache_lowmem_prunes    133483
Qcache_not_cached   43555
Qcache_queries_in_cache 41691
Qcache_total_blocks 103951

我用谷歌搜索发现了关于5.7的许多问题,但是却不明白为什么这个sql出现这种奇怪的行为(仍然有很多其他的sql在5.7上运行得慢得多)。

这是Neville K建议的解释:

id  select_type     table               partitions  type        possible_keys   key         key_len     ref rows filtered Extra
1   SIMPLE      user_table_alias        NULL        ALL         PRIMARY     NULL        NULL        NULL 104801 10.00 Using where; Usingtemporary; Usingfilesort
1   SIMPLE      u               NULL        eq_ref      PRIMARY     PRIMARY     4       knn.base_user_table_alias.id 1 100.00 NULL
1   SIMPLE      user_suspend_table_alias    NULL        ref         userId userId           5       knn.base_user_table_alias.id 1 10.00 Using where;

INNER JOIN user user_table_alias ON user_table_alias. id = u . id INNER JOIN user user_table_alias ON user_table_alias. id = u . id INNER JOIN user user_table_alias ON user_table_alias. id = u . id看起来没用。 它仅与自身连接,在其余的查询中未使用该技术。

emailVerify上没有索引。 由EXPLAIN的第一行指示。 (“在哪里使用”表示不使用索引)

此查询不能很好地扩展表的大小,因为在界定“最近的用户”之前,必须先查看整个表。 因此,myisam使用的某些内部缓冲区现在可能已溢出。 这就是“使用临时”的意思。 使用文件排序意味着顺序很大,因此使用了临时文件,这对性能不利。

好的,感谢NevilleK在Explain上的发言。

我想出了如何仅修复此SQL:

 user_table_alias.emailVerify = 1 

u.emailVerify = 1

我不知道为什么,但是在MySQL5.6中,两者都以毫秒为单位执行。

我想我得回顾所有SQL(来自其他开发者),这要归功于MySQL的向后改进

自连接看起来很多余。

我认为您可以按以下方式重新编写查询:

SELECT
    `u`.*
FROM
    `user` AS `u`
LEFT JOIN `user_suspend` user_suspend_table_alias ON user_suspend_table_alias.`userId` = `u`.`id`
WHERE    `user_suspend_table_alias`.`id` IS NULL
AND      `u`.`emailVerify` = 1
ORDER BY
    `u`.`joinStamp` DESC
LIMIT 1, 18

我假设“ emailVerify”是仅包含少量值(0和1)的列,因此不应该对其进行索引。 我还假定“ joinStamp”是某种时间戳(尽管数据类型是整数)。 如果是这样,您可以创建一个索引来进一步加快速度。

create index id_joinstamp on user (id, joinstamp)

作为解决方法,您可以在首次选择后尝试使用关键字STRAIGHT_JOIN。 此关键字强制mysql从左到右连接( MYSQL-STRAIGHT_JOIN在此代码中做什么? )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM