线上MySQL慢查询现象案例--Impossible WHERE noticed after reading const tables

前言:2012年的笔记整理而得,发布我的博客,作备忘录使用。
背景:线上慢查询日志监控,获得以下的语句:
       发现:select doc_text from t_wiki_doc_text where doc_title = '谢泽源'; 这条语句昨天执行特别的慢

1.查看上述语句的执行计划:
  mysql> explain select doc_text from t_wiki_doc_text where doc_title = '谢泽源';
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL |  Impossible WHERE noticed after reading const tables |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
1 row in set (0.01 sec)
发现了Impossible where noticed after reading const tables,这是一个有趣的现象?(经查找,这个会全表扫描)

解释缘由以下:
根据主键查询或者惟一性索引查询,若是这条数据没有的话,它会全表扫描,而后得出一个结论,该数据不在表中。
对于高并发的库来讲,这条数据,会让负载特别的高。

查看线上的表结构,也印证的上述说法:

| t_wiki_doc_text | CREATE TABLE `t_wiki_doc_text` (
`DOC_ID` bigint(12) NOT NULL COMMENT '词条ID流水号',
`DOC_TITLE` varchar(255) NOT NULL COMMENT '条目原始标题',
`DOC_TEXT` mediumtext COMMENT '条目正文',
PRIMARY KEY (`DOC_ID`),
UNIQUE KEY `IDX_DOC_TITLE` (`DOC_TITLE`)(惟一索引)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

对此,我在本身的数据库里面,作了一个测试。

----------------------------------------------------测试模拟-----------------------------------------------------------
1).创建一个有惟一索引的表。
CREATE TABLE `zsd01` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
UNIQUE KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk


2).插入两条数据
insert into zsd01 values(1,'a');
insert into zsd01 values(2,'b');

3).分析一个没有数据记录的执行计划。(例如select name from zsd01 where name ='c'; )
mysql> explain select name from zsd01 where name ='c';
+----+-------------+-------+------+---------------+------+---------+------+-----
-+-----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows
| Extra |
+----+-------------+-------+------+---------------+------+---------+------+-----
-+-----------------------------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL
Impossible WHERE noticed after reading const tables |
+----+-------------+-------+------+---------------+------+---------+------+-----
-+-----------------------------------------------------+

发现跟上述状况如出一辙。

4.) 修改表结构为只有通常索引的状况。
CREATE TABLE `zsd01` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
KEY `idx_normal_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk

5.) 查看执行计划。
mysql> explain select name from zsd01 where name ='c';
+----+-------------+-------+------+-----------------+-----------------+---------
+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len
| ref | rows | Extra |
+----+-------------+-------+------+-----------------+-----------------+---------
+-------+------+--------------------------+
| 1 | SIMPLE | zsd01 | ref | idx_normal_name | idx_normal_name | 43
| const | 1 | Using where; Using index |
+----+-------------+-------+------+-----------------+-----------------+---------
+-------+------+--------------------------+
1 row in set (0.00 sec)
发现,就正常走了通常索引,rows=1的执行开销。

结论: 从上述的例子和现象能够看出,若是数据不用惟一的话,普通的索引比惟一索引更好用。
相关文章
相关标签/搜索