• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

一个用户SQL慢查询分析,原因及优化_MySQL

mysql 搞代码 4年前 (2022-01-09) 34次浏览 已收录 0个评论

问题描述

<code style="font-family: inherit;font-size: 14px;padding: 0px;color: inherit;background-color: transparent;border: 0px">一个用户反映先上一个SQL语句执行时间慢得无法接受。SQL语句看上去很简单(本文描述中修改了表名和字段名):SELECT count(*)FROMaJOINb ONa.`S` = b.`S` WHERE a.`L` > '2014-03-30 00:55:00' AND a.`L` < '2014-03-30 01:00:00' ; 且查询需要的字段都建了索引,表结构如下:CREATE TABLE `a` (`L` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00',`I` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,`A` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,`S` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,`F` tinyint(4) DEFAULT NULL,`V` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '',`N` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,KEY `IX_L` (`L`),KEY `IX_I` (`I`),KEY `IX_S` (`S`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE `b` (`R` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00',`V` varchar(32) DEFAULT NULL,`U` varchar(32) DEFAULT NULL,`C` varchar(16) DEFAULT NULL,`S` varchar(64) DEFAULT NULL,`I` varchar(64) DEFAULT NULL,`E` bigint(32) DEFAULT NULL,`ES` varchar(128) DEFAULT NULL,KEY `IX_R` (`R`),KEY `IX_C` (`C`),KEY `IX_S` (`S`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;从语句看,这个查询计划很自然的,就应该是先用a作为驱动表,先后使用 a.L和b.S这两个索引。而实际上explain的结果却是:+----+-------------+-------+-------+---------------+------+---------+----------+---------+-------------+| id | select_type | table | type| possible_keys | key| key_len | ref| rows| Extra |+----+-------------+-------+-------+---------------+------+---------+----------+---------+-------------+|1 | SIMPLE| b | index | IX_S| IX_S | 195 | NULL | 1038165 | Using index ||1 | SIMPLE| a | ref | IX_L,IX_S | IX_S | 195 | test.b.S | 1 | Using where |+----+-------------+-------+-------+---------------+------+---------+----------+---------+-------------+</code>

分析

<code style="font-family: inherit;font-size: 14px;padding: 0px;color: inherit;background-color: transparent;border: 0px">从explain的结果看,查询用了b作为驱动表。上一篇文章我们介绍到,MySQL选择jion顺序是分别分析各种join顺序的代价后,选择最小代价的方法。这个join只涉及到两个表,自然也与optimizer_search_depth无关。于是我们的问题就是,我们预期的那个join顺序的为什么没有被选中?MySQL Tips: MySQL提供straight_join语法,强制设定连接顺序。explain SELECT count(*)FROMastraight_joinb ONa.`S` = b.`S` WHERE a.`L` > '2014-03-30 00:55:00' AND a.`L` < '2014-03-30 01:00:00' ;+----+-------------+-------+-------+---------------+------+---------+------+---------+---------------------------------------------+| id | select_type | table | type| possible_keys | key| key_len | ref| rows| Extra |+----+-------------+-------+-------+---------------+------+---------+------+---------+---------------------------------------------+|1 | SIMPLE| a | range | IX_L,IX_S | IX_L | 4 | NULL |63 | Using where ||1 | SIMPLE| b | index | IX_S| IX_S | 195 | NULL | 1038165 | Using where; Using index; Using join buffer |+----+-------------+-------+-------+---------------+------+---------+------+---------+--------------------------------<mark style="color:transparent">来4源gaodaimacom搞#代%码*网</mark>-------------+</code>
<code style="font-family: inherit;font-size: 14px;padding: 0px;color: inherit;background-color: transparent;border: 0px">MySQL Tips: explain结果中,join的查询代价可以用依次连乘rows估算。</code>
<code style="font-family: inherit;font-size: 14px;padding: 0px;color: inherit;background-color: transparent;border: 0px">join顺序对了,简单的分析查询代价:普通join是1038165*1, straight_join是 63*1038165. 貌似MySQL没有错。但一定哪里不对!</code>

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:一个用户SQL慢查询分析,原因及优化_MySQL
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址