返回顶部
首页 > 资讯 > 数据库 >《MySQL面试小抄》索引失效场景验证
  • 687
分享到

《MySQL面试小抄》索引失效场景验证

《MySQL面试小抄》索引失效场景验证 2018-01-04 14:01:37 687人浏览 无得
摘要

我是肥哥,一名不专业的面试官! 我是囧囧,一名积极找工作的小菜鸟! 囧囧表示:小白面试最怕的就是面试官问的知识点太笼统,自己无法快速定位到关键问题点!!! 本期主要面试考点 面试官考点之什么情况下会索引失效? 本期验证以下索引失效

《MySQL面试小抄》索引失效场景验证

我是肥哥,一名不专业的面试官!

我是囧囧,一名积极找工作的小菜鸟!

囧囧表示:小白面试最怕的就是面试官问的知识点太笼统,自己无法快速定位到关键问题点!!!


本期主要面试考点

面试官考点之什么情况下会索引失效?

本期验证以下索引失效的常见场景

like通配符,左侧开放情况下,全表扫描
2、or条件筛选,可能会导致索引失效
3、where中对索引列使用Mysql的内置函数,一定失效
4、where中对索引列进行运算(如,+、-、*、/),一定失效
5、类型不一致,隐式的类型转换,导致的索引失效
6、where语句中索引列使用了负向查询,可能会导致索引失效。负向查询包括:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,其中:!< !> sqlServer语法。
7、索引字段可以为null,使用is null或is not null时,可能会导致索引失效
8、隐式字符编码转换导致的索引失效
9、联合索引中,where中索引列违背最左匹配原则,一定会导致索引失效
10、mysql优化器的最终选择,不走索引

索引失效验证1

索引失效验证1

验证准备

准备数据表,同时建立普通索引 idx_user_name

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL,
  `user_name` varchar(32) CHARACTER DEFAULT NULL COMMENT "用户名",
  `address` varchar(255) CHARACTER DEFAULT NULL COMMENT "地址",
  `create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT "创建时间",
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入1万条数据(注意:数据多些,mysql不走索引情况之一是数据量非常少,MySQL查询优化器认为全表扫描比使用索引更快,导致索引失效,explain检查是否使用索引时,发现无法走索引)

-- 创建存储过程,插入10000用户信息
CREATE PROCEDURE user_insert()
-- 定义存储过程开始
BEGIN
	-- 定义变量 i ,int 类型,默认值为 1
	DECLARE i INT DEFAULT 1;
	
	WHILE i <= 10000
		-- 定义循环内执行命令
		DO INSERT INTO t_user(id, user_name, address, create_time) VALUES(i, CONCAT("mayun", i), CONCAT("浙江杭州", i), now());
		SET i=i+1;
	END WHILE;
	
	COMMIT;
END;
-- 定义存储过程结束


-- 调用存储工程
CALL user_insert();

一、OR索引失效验证

好多人说where条件中使用 or ,那么索引一定失效,是否正确?

or查询

OR 连接的是同一个字段,相同走索引

explain select * from t_user where user_name = "mayun10" or user_name = "mayun1000"

or查询走索引情况

OR 连接的是两个不同字段,不同索引失效

explain select * from t_user where user_name = "mayun10" or address = "浙江杭州12"

or查询索引失效情况

给address列增加索引

alter table t_user add index idx_address (address)

OR 连接的是两个不同字段,如果两个字段皆有索引,走索引

or查询走索引情况-两边字段有索引

验证总结

or 可能会导致索引失效,并非一定,这里涉及到MySQL index merge 技术。

MySQL5.0之前,查询时一个表一次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。

但是从5.1开始,MySQL引入了 index merge 优化技术,对同一个表可以使用多个索引分别进行条件扫描。然后将它们各自的结果进行合并(intersect/uNIOn)。

or索引生效有哪些情况?

第一种 or两边连接的是同一个索引字段

第二种 or两边连接的是两个索引字段,即两个字段分别都建立了索引

二、LIKE通配符索引失效验证

一个最常见的查询场景,建立idx_user_name索引

select * from t_user where user_name like "%mayun100%";

这条查询是否走索引?

like不走索引

select * from t_user where user_name like "mayun100%";

这条查询是否走索引?

like走索引

验证总结

like 通配符特性是可以左右开闭匹配查询当左边开放使用 % 或者 _ 匹配的时候都不会走索引,会进行全表扫描

为什么左开情况下会索引失效?请介绍一下原理!

我们知道建立索引后,MySQL会建立一棵有序的B+Tree,索引树是有序的,索引列进行查询匹配时是从左到右进行匹配。使用 % 和 _ 匹配,这表示左边匹配值是不确定的。不确定,意味着充满可能,怎么比较?

当然只能一个一个的比较,那就相当于,全匹配了,全匹配在优化器看来,与其走索引树查询,再进行不断的回表操作,还不如直接进行全表扫描划算!

三、where中对索引列使用mysql的内置函数

建立 idx_age 索引,

alter table t_user add index idx_age(age);

不使用内置函数

explain select * from t_user where age = 80

内置函数验证-不使用内置函数

使用内置函数

explain select * from t_user where abs(age) = 80

内置函数验证-内置函数

验证总结

如果对索引字段做了函数操作,可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能。

MySQL 无法再使用索引快速定位功能,而只能使用全索引扫描。

四、where中对索引列进行运算(如,+、-、*、/),一定失效

不涉及索引列的运算

alter table t_user add index idx_age(age);explain select * from t_user where age = 80;

内置函数验证-不使用内置函数

索引列进行运算操作

explain select * from t_user where age + 5 = 80

索引运算失效

五、类型不一致,隐式的类型转换,导致的索引失效

alter table t_user add index idx_user_name(user_name);explain select * from t_user where user_name = "mayun1";

类型不一致验证之正常类型

修改数据,再次explain

update t_user set user_name = "100" where user_name = "mayun1";explain select * from t_user where user_name = 100;

user_name = 100 ,因为user_name 字段定义的是varchar,索引在where进行匹配时会先隐式调用 case() 函数进行类型转换 将匹配条件变成,user_name = "100"

类型不一致验证之类型转换

六、where语句中索引列使用了负向查询,可能会导致索引失效。

负向查询包括:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,其中:!< !> SQLServer语法。

alter table t_user add index idx_age(age);explain select * from t_user where age in (100, 50);

反向选择之in

explain select * from t_user where age not in (100, 50);

反向选择之not_in

七、索引字段可以为null,使用is null或is not null时,可能会导致索引失效

第一种情况,表结构规定允许user_name 字段可以为null

null可以为空

explain select * from t_user where user_name is null;

null可以为空校验之is_null

explain select * from t_user where user_name is not null;

null可以为空校验之is_not_null

第二种情况,表结构规定user_name 字段不可以为null

null不允许为null

explain select * from t_user where user_name is null;

null不允许为null之null

explain select * from t_user where user_name is not null;

null不允许为null之is_not_null

八、隐式字符编码转换导致的索引失效

当两个表进行连接JOIN 时,如果两张表的字符编码不同,可能会导致索引失效。

这个索引失效场景尚未遇到,网上很多文章说会导致索引失效,查阅发现大量的博客说UTF8mb4字符集的表mb4与UTF8字符集的表utf8 关联会产生索引失效的问题,但是我根据大量博文所述操作,发现暂时还是无法复现,读者可自行查阅。

如果读者复现到此场景,欢迎评论讨论或关注如果读者复现到此场景,欢迎评论或关注公众号囧么肥事讨论

九、联合索引中,where中索引列违背最左匹配原则,一定会导致索引失效

创建联合做引 idx_user_name_deposit, 遵循最左匹配原则

alter table t_user add index idx_user_name_deposit(user_name, deposit);explain select * from t_user where user_name like "mayun86%"

最左匹配之a

遵循最左匹配之 a b 类型

explain select * from t_user where user_name like "mayun86%" and deposit = 5620.26;

最左匹配之ab

调换索引位置,测试联合索引书写规则

explain select * from t_user where deposit = 5620.26 and user_name like "mayun86%";

最左匹配之ba

违反最左匹配原则

explain select * from t_user where deposit = 5620.26;

最左匹配之b

验证总结

联合索引依据最左匹配原则建立索引树,在查询时依据联合索引顺序依次匹配索引值,查询时如果违背最左匹配原则,将导致索引失效。

假设建立索引 idx_a_b_c,相当于建立了 (a), (a,b), (a,b,c)三个索引查询匹配时匹配顺序是 a b c 查询时如果没有 a 字段筛选,那么索引将失效

举栗子,走索引情况

select * from test where a=1 select * from test where a=1 and b=2 select * from test where a=1 and b=2 and c=3

索引失效呢?

select * from test where b=2 and c=3

联合索引如果要走索引,查询条件中必须要包含第一个索引,否则索引失效

select * from test where b=1 and a=1select * from test where m="222" and a=1

这两条查询走索引的原因是什么?

最左前缀指的是查询时匹配索引列要按照联合索引创建的顺序,但是在书写时不需要严格按照联合索引创建的顺序,MySQL优化器会自动调整,所以上面两条查询索引有效!

十、MySQL优化器的最终选择,不走索引

explain select * from t_user where age > 59;

优化器不走

explain select * from t_user where age > 99;

优化器走

验证总结

MySQL查询索引失效的情况有很多,即使其他情况都规避,但是在经过了优化器的确定查询方案的时候,依然可能索引失效。

优化器会考虑查询成本,来确认它认为的最佳方案来执行查询

当数据量较少,或者需要访问行很多的时候

优化器会认为走索引树来进行回表,还不如直接进行全表扫描的时候,优化器将会抛弃走索引树。

随缘更新,大神请绕路!

更多精彩内容,欢迎关注微信公众号:囧么肥事 (或搜索:jiongmefeishi)

您可能感兴趣的文档:

--结束END--

本文标题: 《MySQL面试小抄》索引失效场景验证

本文链接: https://lsjlt.com/news/8530.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 《MySQL面试小抄》索引失效场景验证
    我是肥哥,一名不专业的面试官! 我是囧囧,一名积极找工作的小菜鸟! 囧囧表示:小白面试最怕的就是面试官问的知识点太笼统,自己无法快速定位到关键问题点!!! 本期主要面试考点 面试官考点之什么情况下会索引失效? 本期验证以下索引失效...
    99+
    2018-01-04
    《MySQL面试小抄》索引失效场景验证
  • 《MySQL面试小抄》索引考点二面总结
    《MySQL面试小抄》索引考点二面总结 我是肥哥,一名不专业的面试官! 我是囧囧,一名积极找工作的小菜鸟! 囧囧表示:小白面试最怕的就是面试官问的知识点太笼统,自己无法快速定位到关键问题点!!!   本期主要面试考点 面试官考点之谈...
    99+
    2021-10-15
    《MySQL面试小抄》索引考点二面总结
  • Mysql索引失效场景有哪些
    这篇文章主要介绍Mysql索引失效场景有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!数据库及索引准备创建表结构为了逐项验证索引的使用情况,我们先准备一张表t_user:CREA...
    99+
    2024-04-02
  • MySQL索引失效的场景有哪些
    以下是一些导致MySQL索引失效的常见场景: 使用不符合最左前缀原则的查询条件:当查询条件中的列不是索引的最左前缀时,MySQL...
    99+
    2024-04-09
    MySQL
  • MySQL索引失效场景及解决方案
    目录一、前言二、最左前缀匹配原则三、mysql逻辑架构和优化器四、索引失效场景以及为何会失效五、总结一、前言 在对SQL语句进行索引查询时会遇到索引失效的时候,对于该语句的可行性以及性能效率方面有至关重要的影响,本篇剖析...
    99+
    2022-07-22
    MySQL索引失效场景解决方案 MySQL索引失效
  • 分享15个Mysql索引失效的场景
    目录背景1.数据库及索引准备创建表结构初始化数据数据库版本及执行计划2.联合索引不满足最左匹配原则3.使用了select *4.索引列参与运算5.索引列参使用了函数6.错误...
    99+
    2024-04-02
  • MySQL索引失效十种场景与优化方案
    目录1 数据准备1.1 新建数据表1.2 新增100万条数据2 基础知识2.1 explain type2.2 explain Extra3 索引失效场景3.1 查询类型错误3.1....
    99+
    2023-05-19
    MySQL索引失效场景 MySQL索引优化 MySQL索引失效与优化
  • MySQL数据库索引以及失效场景详解
    目录1. MySQL索引概述1.1 索引的概念1.2 索引的特点1.3 索引的分类1.4 索引的使用场景2. 索引失效场景2.1 索引失效9种场景2.2 索引失效场景总结3. 索引失...
    99+
    2024-04-02
  • MySQL中索引失效的常见场景与规避方法
    前言 之前有看过许多类似的文章内容,提到过一些sql语句的使用不当会导致MySQL的索引失效。还有一些MySQL“军规”或者规范写明了某些sql不能这么写,否则索引失效。 绝大部分的内容笔者是认可的,不...
    99+
    2024-04-02
  • mysql索引失效的十大问题小结
    目录背景一、查询条件包含or,可能导致索引失效二、如何字段类型是字符串,where时一定用引号括起来,否则索引失效三、like通配符可能导致索引失效。四、联合索引,查询时的...
    99+
    2024-04-02
  • MySQL索引失效的几种情况小结
    目录1.最左前缀原则2. 计算、函数使索引失效3. 类型转换导致索引失效4. 不等于(<>或!=)导致索引失效5. is not null /is null可能不走索引,也可以走索引6. 模糊匹配Like以%...
    99+
    2023-03-20
    MySQL索引失效 数据库索引失效
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作