面试官:讲讲MySql索引失效的几种情况
索引失效
准备数据:
CREATE TABLE `dept` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`deptName` VARCHAR(30) DEFAULT NULL,
`address` VARCHAR(40) DEFAULT NULL,
ceo INT NULL ,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1;
CREATE TABLE `emp` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`empno` INT NOT NULL ,
`name` VARCHAR(20) DEFAULT NULL,
`age` INT(3) DEFAULT NULL,
`deptId` INT(11) DEFAULT NULL,
PRIMARY KEY (`id`)
#CONSTRAINT `fk_dept_id` FOREIGN KEY (`deptId`) REFERENCES `t_dept` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1;
1、计算、函数导致索引失效
-- 显示查询分析
EXPLAIN SELECT * FROM emp WHERE emp.name LIKE 'abc%';
EXPLAIN SELECT * FROM emp WHERE LEFT(emp.name,3) = 'abc'; --索引失效

2、LIKE以%开头索引失效
EXPLAIN SELECT * FROM emp WHERE name LIKE '%ab%'; --索引失效

拓展:Alibaba《Java开发手册》
【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
3、不等于(!= 或者<>)索引失效
EXPLAIN SELECT * FROM emp WHERE emp.name = 'abc' ;
EXPLAIN SELECT * FROM emp WHERE emp.name <> 'abc' ; --索引失效

4、IS NOT NULL 和 IS NULL
EXPLAIN SELECT * FROM emp WHERE emp.name IS NULL;
EXPLAIN SELECT * FROM emp WHERE emp.name IS NOT NULL; --索引失效

注意:当数据库中的数据的索引列的NULL值达到比较高的比例的时候,即使在IS NOT NULL 的情况下 MySQL的查询优化器会选择使用索引,此时type的值是range(范围查询)
-- 将 id>20000 的数据的 name 值改为 NULL
UPDATE emp SET `name` = NULL WHERE `id` > 20000;
-- 执行查询分析,可以发现 IS NOT NULL 使用了索引
-- 具体多少条记录的值为NULL可以使索引在IS NOT NULL的情况下生效,由查询优化器的算法决定
EXPLAIN SELECT * FROM emp WHERE emp.name IS NOT NULL;

测试完将name的值改回来
UPDATE emp SET `name` = rand_string(6) WHERE `id` > 20000;
5、类型转换导致索引失效
EXPLAIN SELECT * FROM emp WHERE name='123';
EXPLAIN SELECT * FROM emp WHERE name= 123; --索引失效

6、全值匹配我最爱
准备:
-- 首先删除之前创建的索引
CALL proc_drop_index("atguigudb","emp");
问题:为以下查询语句创建哪种索引效率最高
-- 查询分析
EXPLAIN SELECT * FROM emp WHERE emp.age = 30 and deptid = 4 AND emp.name = 'abcd';
-- 执行SQL
SELECT * FROM emp WHERE emp.age = 30 and deptid = 4 AND emp.name = 'abcd';
-- 查看执行时间
SHOW PROFILES;
创建索引并重新执行以上测试:
-- 创建索引:分别创建以下三种索引的一种,并分别进行以上查询分析
CREATE INDEX idx_age ON emp(age);
CREATE INDEX idx_age_deptid ON emp(age,deptid);
CREATE INDEX idx_age_deptid_name ON emp(age,deptid,`name`);
结论:可以发现最高效的查询应用了联合索引 idx_age_deptid_name

7、最佳左前缀法则
准备:
-- 首先删除之前创建的索引
CALL proc_drop_index("atguigudb","emp");
-- 创建索引
CREATE INDEX idx_age_deptid_name ON emp(age,deptid,`name`);
问题:以下这些SQL语句能否命中 idx_age_deptid_name 索引,可以匹配多少个索引字段
测试:
- 如果索引了多列,要遵守最左前缀法则。即查询从
索引的最左前列开始并且不跳过索引中的列。 - 过滤条件要使用索引,必须按照
索引建立时的顺序,依次满足,一旦跳过某个字段,索引后面的字段都无法被使用。
EXPLAIN SELECT * FROM emp WHERE emp.age=30 AND emp.name = 'abcd' ;
-- EXPLAIN结果:
-- key_len:5 只使用了age索引
-- 索引查找的顺序为 age、deptid、name,查询条件中不包含deptid,无法使用deptid和name索引
EXPLAIN SELECT * FROM emp WHERE emp.deptid=1 AND emp.name = 'abcd';
-- EXPLAIN结果:
-- type: ALL, 执行了全表扫描
-- key_len: NULL, 索引失效
-- 索引查找的顺序为 age、deptid、name,查询条件中不包含age,无法使用整个索引
EXPLAIN SELECT * FROM emp WHERE emp.age = 30 AND emp.deptid=1 AND emp.name = 'abcd';
-- EXPLAIN结果:
-- 索引查找的顺序为 age、deptid、name,匹配所有索引字段
EXPLAIN SELECT * FROM emp WHERE emp.deptid=1 AND emp.name = 'abcd' AND emp.age = 30;
-- EXPLAIN结果:
-- 索引查找的顺序为 age、deptid、name,匹配所有索引字段
8、索引中范围条件右边的列失效
准备:
-- 首先删除之前创建的索引
CALL proc_drop_index("atguigudb","emp");
问题:为以下查询语句创建哪种索引效率最高
EXPLAIN SELECT * FROM emp WHERE emp.age=30 AND emp.deptId>1000 AND emp.name = 'abc';
测试1:
-- 创建索引并执行以上SQL语句的EXPLAIN
CREATE INDEX idx_age_deptid_name ON emp(age,deptid,`name`);
-- key_len:10, 只是用了 age 和 deptid索引,name失效
注意:当我们修改deptId的范围条件的时候,例如deptId>100,那么整个索引失效,MySQL的优化器基于成本计算后认为没必要使用索引了,所以就进行了全表扫描。(注意:因为表中的数据是随机生成的,因此实际测试中根据具体数据的不同测试的结果也会不一样,最终是否使用索引由优化器决定)

测试2:
-- 创建索引并执行以上SQL语句的EXPLAIN(将deptid索引的放在最后)
CREATE INDEX idx_age_name_deptid ON emp(age,`name`,deptid);
-- 使用了完整的索引

补充:以上两个索引都存在的时候,MySQL优化器会自动选择最好的方案
面试官:讲讲MySql索引失效的几种情况的更多相关文章
- mysql索引总结(4)-MySQL索引失效的几种情况
mysql索引总结(1)-mysql 索引类型以及创建 mysql索引总结(2)-MySQL聚簇索引和非聚簇索引 mysql索引总结(3)-MySQL聚簇索引和非聚簇索引 mysql索引总结(4)-M ...
- MySQL索引失效的几种情况
1.索引不存储null值 更准确的说,单列索引不存储null值,复合索引不存储全为null的值.索引不能存储Null,所以对这列采用is null条件时,因为索引上根本 没Null值,不能利用到索引, ...
- mysql 索引失效的几种情况+
- 【转-mysql索引失效的几种情形】
索引并不是时时都会生效的,比如以下几种情况,将导致索引失效: 1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因) 注意:要想使用or,又想让索引生效,只能将or条件 ...
- MySQL索引失效的几种场景
我们都知道建立索引能够提高查询效率,那么是不是任何情况下都能提高呢,当然不是的的,下面我们就来列举一些常见的索引失效的场景. 借用上一篇文章的dm_person_info表 在card_code列没加 ...
- oracle数据库中索引失效的几种情况
原文1:https://blog.csdn.net/u012255097/article/details/102792683 原文2:https://www.cnblogs.com/lanseyita ...
- 【原创】面试官:讲讲mysql表设计要注意啥
引言 近期由于复习了一下mysql的内容,有些心得.随手讲其中一部分知识,都是一些烟哥自己平时工作的总结以及经验.大家看完,其实能避开很多坑.而且很多问题,都是面试中实打实会问到的! 比如 OK,具体 ...
- <转载>面试官: 讲讲MySql表设计需要注意什么?
作者:孤独烟 出处: http://rjzheng.cnblogs.com/ 综述 近期由于复习了一下MySQL的内容看到一篇比较好的文章,转载分享一下.大家看完,其实能避开很多坑.而且很多问题,都是 ...
- 面试官:讲讲mysql表设计要注意啥
内容时参考一个博主的,内容写的很好,就忍不住拿过来了,如遇到,请见谅 参考连接:https://www.cnblogs.com/rjzheng/p/11174714.html
- mysql——索引失效
索引失效的几种情况:https://www.jianshu.com/p/9c9a0057221f
随机推荐
- 人工智能 deepface 换脸技术 学习
介绍 Deepface是一个轻量级的python人脸识别和人脸属性分析(年龄.性别.情感和种族)框架.它是一种混合人脸识别框架缠绕状态的最先进的模型:VGG-Face,Google FaceNet,O ...
- mesql输入中文报错
错误提示:ERROR 1366 (HY000): Incorrect string value: '\xE6\x9D\x8E\xE5\x8B\x87' for column 'Sname' at ro ...
- Jmix 如何将外部数据直接显示在界面?
企业级应用中,通常一个业务系统并不是孤立存在的,而是需要与企业.部门或者是外部的已有系统进行集成.一般而言,系统集成的数据和接口交互方式通常有以下几种: 文件传输:通过文件传输的方式将数据传递给其他系 ...
- Mybatis 框架下 SQL 注入攻击的方式
前言 SQL注入漏洞作为WEB安全的最常见的漏洞之一,在java中随着预编译与各种ORM框架的使用,注入问题也越来越少. 新手代码审计者往往对Java Web应用的多个框架组合而心生畏惧,不知如何下手 ...
- LeeCode 动态规划(一)
简述 如果某一问题存在很多重叠子问题,使用动态规划是非常有效的. 动态规划与贪心 贪心:每次都选择局部最优解 动态规划:每个状态都是由前一个状态推导得到 动态规划解题步骤 确定 dp数组 及下标的含义 ...
- Poe – Fast AI Chat 一款集成AI工具
前言 Poe – Fast AI Chat是由知名问答社区 Quora 开发的 AI 产品,提供实时在线与多个 AI 机器人交流的功能.在去年12月,Quora首次推出Poe作为封闭测试版,并于2月份 ...
- Rocky Linux 初体验
简介 Rocky Linux 是 CentOS 的一个分支,它位于 Red Hat Enterprise Linux(RHEL) 的下游.与 CentOS 一样,它提供了非常适合服务器的稳定版 Lin ...
- STM32 + RTThread + UGUI
一.概述 开发板:STM32F103C8T6 显示器:ST7735S RT-Thread:5.0.0 玩过 GUI 的小伙伴都知道,界面的显示是一个个像素点组合起来的,那么直接构建出来炫酷的 GUI ...
- [ [Ynoi2013] 无力回天 NOI2017 ] 解题报告
[Ynoi2013] 无力回天 NOI2017 首先看到异或,想到能维护异或的东西就那几样(线性基/01trie/数位 dp/FWT),再看到求选任意个数后的异或最大值,线性基无疑了. 这时再看还要维 ...
- java线程池和多线程的使用详解
Java 多线程和线程池使用 java多线程实现的几种方法 1.继承Thread类 继承Thread类,重写run方法,创建线程类对象调用start方法启动线程. public class Threa ...