MySQL索引失效的情况
文章目录
CREATE TABLE `library` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`book_name` varchar(20) NOT NULL COMMENT '书名',
`author` varchar(20) NOT NULL COMMENT '作者',
`position` varchar(20) NOT NULL COMMENT '位置',
`brief` varchar(500) DEFAULT NULL COMMENT '描述',
PRIMARY KEY (`id`),
KEY `index_book_name` (`book_name`),
KEY `index_author` (`author`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='图书表';
INSERT INTO `test-index`.`library` (`id`, `book_name`, `author`, `position`, `brief`) VALUES ('1', '西游记', '吴承恩', '1楼7A', '《西游记》是一部中国古典神魔小说,为中国“四大名著”之一《西游记》是一部中国古典神魔小说,为中国“四大名著”之一');
INSERT INTO `test-index`.`library` (`id`, `book_name`, `author`, `position`, `brief`) VALUES ('2', '三国演义', '罗贯中', '1楼7B', '1231131');
INSERT INTO `test-index`.`library` (`id`, `book_name`, `author`, `position`, `brief`) VALUES ('3', '小说A', '张三', '1楼1C', '121212');
INSERT INTO `test-index`.`library` (`id`, `book_name`, `author`, `position`, `brief`) VALUES ('4', '小说B', '李四', '2楼2B', '7887');
INSERT INTO `test-index`.`library` (`id`, `book_name`, `author`, `position`, `brief`) VALUES ('5', '小说C', '王五', '6楼1A', '8989');
索引字段为:id是主键索引,book_name和author为普通索引
1.索引字段使用 or 时,会导致索引失效而转向全表扫描
1.执行语句:
explain select position from library where book_name='西游记' or position='1楼7A';
解释:搜索条件为一个索引列,一个非索引列,不走索引
2.执行语句:
explain select position from library where book_name='西游记' or author='吴承恩';
在这里插入图片描述
解释:搜索条件都为索引列时(网上很多说走),不走索引,此处是InnoDB存储引擎,当为MyISAM走索引,
证明:
执行语句:
explain select position from library2 where book_name='西游记' or author='吴承恩';
执行计划可以看出是走的索引的
2.对于多列索引,不是使用的第一部分(第一个),则不会使用索引
3.like查询是以%开头
explain select position from library where book_name like '%游记';
4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来
5.其他情况
1) 没有查询条件,或者查询条件没有建立索引
2) 在查询条件上没有使用引导列
3) 查询的数量是大表的大部分,应该是30%以上。
4) 索引本身失效
5) 查询条件使用函数在索引列上,或者 对索引列进行运算, 运算包括(+,-,*,/,! 等) 错误的例子:select * from test where id-1=9; 正确的例子:select * from test where id=10;
6) 对小表查询
7) 提示不使用索引
8) 统计数据不真实
9) CBO计算走索引花费过大的情况。其实也包含了上面的情况,这里指的是表占有的block要比索引小。
10)隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误. 由于表的字段tu_mdn定义为varchar2(20),但在查询时把该字段作为number类型以where条件传给Oracle,这样会导致索引失效. 错误的例子:select * from test where tu_mdn=13333333333; 正确的例子:select * from test where tu_mdn='13333333333';
12) 1,<> 2,单独的>,<,(有时会用到,有时不会)
13,like "%_" 百分号在前.
14,单独引用复合索引里非第一位置的索引列.
15,字符型字段为数字时在where条件里不添加引号.
16,对索引列进行运算.需要建立函数索引.
17,not in ,not exist.
18,当变量采用的是times变量,而表的字段采用的是date变量时.或相反情况。
19,B-tree索引 is null不会走,is not null会走,位图索引 is null,is not null 都会走
20,联合索引 is not null 只要在建立的索引列(不分先后)都会走, in null时 必须要和建立索引第一列一起使用,当建立索引第一位置条件是is null 时,其他建立索引的列可以是is null(但必须在所有列 都满足is null的时候),或者=一个值; 当建立索引的第一位置是=一个值时,其他索引列可以是任何情况(包括is null =一个值),以上两种情况索引都会走。其他情况不会走。