簡體   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