Mysql数据库表中为什么有索引却没有提高查询速度


Posted in MySQL onFebruary 24, 2022

背景

时间过得太快了,春节假期感觉光速般就结束了,转眼间就要继续搬砖上班了。紧接着很快就要进入金三银四的求职面试高峰期,程序猿小枫还没有找到令自己感到满意的工作。就算是在过年放假期间也在拼命的准备技术面试,这不他又梳理了下之前面试过程中面试官经常问到的关于数据库方面的一道面试题,我们来一起帮小枫看看有没有遗漏的地方吧。

面试题目——问题

面试官:看你的简历中有提到过曾经进行过索引优化的工作,那我就问问你,假设数据库表中有索引,但是进行SQL数据查询还是很慢,这种情况下应该怎么分析查询慢的原因?

分析

在进行数据库查询的时候,我们都知道索引可以加快数据查询的效率。但是在实际的业务场景下,经常会遇到即使在表中增加了索引,但是同样还是会出现数据查询慢的问题。这就需要具体分析数据查询慢的具体原因到底是什么了。

首先需要进行确认的就是SQL语句中对应的条件查询中字段有没有建立索引。虽然面试官说了有索引,但是不一定SQL语句中的查询字段有建立索引,所以第一步应该进行SQL中的字段索引确认。如果没有建立对应的索引可以先尝试下建立索引再进行查询。如果已经有了索引,查询的字段也是索引字段,那么就要考虑下是不是出现了索引失效的情况。下面我们再具体分析下,看看在哪些场景下会出现索引失效的情况。

索引失效场景

在分析索引失效场景之前,我们必须要清楚索引结构的特点是什么。关于Mysql的数据库索引结构在之前的文章中已经进行了详细的分析,可以参见之前的文章。

我们来看下Mysql数据库索引的结构特点:

Mysql数据库表中为什么有索引却没有提高查询速度

 这里以user_info这张表来作为分析的基础,在user_info这张表上,我们分别创建了idx_name以及idx_phone二级索引以及idx_age_address联合索引。

CREATE TABLE IF NOT EXISTS `user_info` (
 `id` bigint(20) NOT NULL AUTO_INCREMENT,
 `name` VARCHAR(20) NOT NULL,
 `gender` int(2) NOT NULL,
 `age` int(10) NOT NULL,
 `phone_number` VARCHAR(20) NOT NULL,
 `address` VARCHAR(40) NOT NULL,
  PRIMARY KEY ( `id` ),
  KEY `idx_name`(`name`),
  KEY `idx_phone`(`phone_number`),
  KEY `idx_age_address`(`age`,`address`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 1、字段类型不匹配导致的索引失效

进行SQL数据查询的时候,where条件字段类型与实际表中字段类型不匹配的时候,Mysql会进行隐式的数据类型转换,而类型转换会使用到内置函数,导致在进行数据查询的时候并没有使用索引。我们可以使用explain命令查看sql语句。可以看的出来在key栏中,对应的值为null,说明并没有使用索引进行查询。 

Mysql数据库表中为什么有索引却没有提高查询速度

 但是如果在按照phone_number字段为字符串类型进行查询的时候,Mysql没有进行隐式的类型转换,所以最终还是走了索引。

Mysql数据库表中为什么有索引却没有提高查询速度

  • 2、被索引字段使用了表达式计算

在where中条件使用了条件表达式的时候,数据表中的索引就失效了,实际是因为Mysql需要将索引字段取出来之后再进行表达式的条件判断,因而进行了全表扫描,导致索引失效。

Mysql数据库表中为什么有索引却没有提高查询速度

  • 3、被索引字段使用了内置函数

索引字段实际上是依赖于整个B+索引树的遍历,而索引树的遍历又依赖于索引树底层叶子节点的有序性。索引保存的是索引列的原始值,如果经过函数计算,Msql的解释器无法判断计算后的索引在原来的索引树上是否可以被索引到,因此它就直接放弃使用索引查询了。

Mysql数据库表中为什么有索引却没有提高查询速度

  • 4、like使用了%X模糊匹配

使用左模糊匹配以及左右模糊匹配都会导致索引失效,但是使用右模糊匹配,还是可以走索引查询的。

Mysql数据库表中为什么有索引却没有提高查询速度

由于B+树按照索引值进行排序的,实际是按照最左前缀进行比较,而使用了%作为最左前缀,Mysql无法判断其有序性,因此只能进行全表扫描查询。

Mysql数据库表中为什么有索引却没有提高查询速度

  • 5、索引字段不是联合索引字段的最左字段

如果数据库表中有联合索引的话,我们在SQL查询语句中使用的索引字段又不是联合索引的最左字段,那么就会导致索引失效。

Mysql数据库表中为什么有索引却没有提高查询速度

实际上在Mysql中的索引检索是遵循最左匹配原则的,同时B+索引树的叶子节点的有序性也是建立都在最左匹配原则之上,而上述的4、5两种情况实际违反了最左匹配原则,因此Mysql执行器则无法使用对应的索引进行检查查询。

Mysql数据库表中为什么有索引却没有提高查询速度

  • 6、or分割的条件,如果or左边的条件存在索引,而右边的条件没有索引,不走索引

因为 OR 的含义就是两个只要满足一个即可,因此只有一个条件列进行了索引是没有意义的,只要有条件列没有进行索引,就会进行全表扫描,因此索引的条件列也会失效。

Mysql数据库表中为什么有索引却没有提高查询速度

  • 7、in、not in可能会导致索引失效

Mysql数据库表中为什么有索引却没有提高查询速度

这里需要说明的是使用in以及not in走不走索引,实际和Mysql的版本以及表中的数据量有关系,在8.0之后的版本是走索引的。

总结

本文根据面试官的存在索引但是出现数据查询慢的问题为出发点,总结了几种索引失效的场景,希望在大家平时项目开发时遇到类似的问题可以有对应的问题排查方向。导致索引失效的场景归结起来实际就是在索引使用上面存在瑕疵最终导致了索引失效的情况,这就像我们小时候打拳皇97一样,遥感和按钮的组合如果姿势不对,就没办法放出我们希望的大招。小枫的求职面试之路还在继续,我们一起期待下次小枫还会遇到怎样的面试问题吧。

到此这篇关于Mysql数据库表中为什么有索引却没有提高查询速度的文章就介绍到这了,更多相关Mysql 数据库表索引内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
MySQL root密码的重置方法
Apr 21 MySQL
MySQL 表空间碎片的概念及相关问题解决
May 07 MySQL
MySQL update set 和 and的区别
May 08 MySQL
MySQL表字段时间设置默认值
May 13 MySQL
MySQL中distinct与group by之间的性能进行比较
May 26 MySQL
MySQL8.0.18配置多主一从
Jun 21 MySQL
MySQL系列之六 用户与授权
Jul 02 MySQL
SQL实现LeetCode(197.上升温度)
Aug 07 MySQL
MySQL数据库中varchar类型的数字比较大小的方法
Nov 17 MySQL
Mysql存储过程、触发器、事件调度器使用入门指南
Jan 22 MySQL
MySQL创建管理HASH分区
Apr 13 MySQL
MySQL 表锁定 LOCK和UNLOCK TABLES的 SQL语法
Apr 18 MySQL
教你如何让spark sql写mysql的时候支持update操作
Feb 15 #MySQL
一文弄懂MySQL中redo log与binlog的区别
Feb 15 #MySQL
Mysql Innodb存储引擎之索引与算法
深入讲解数据库中Decimal类型的使用以及实现方法
Mysql分库分表之后主键处理的几种方法
MySQL 开窗函数
mysql自增长id用完了该怎么办
Feb 12 #MySQL
You might like
PHP5.0对象模型探索之抽象方法和抽象类
2006/09/05 PHP
php遍历目录viewDir函数
2009/12/15 PHP
基于MySQL到MongoDB简易对照表的详解
2013/06/03 PHP
php5.2以下版本无json_decode函数的解决方法
2014/05/25 PHP
php实现根据字符串生成对应数组的方法
2014/09/22 PHP
JS实现随机数生成算法示例代码
2013/08/08 Javascript
Nodejs极简入门教程(二):定时器
2014/10/25 NodeJs
自己编写的支持Ajax验证的JS表单验证插件
2015/05/15 Javascript
laypage分页控件使用实例详解
2016/05/19 Javascript
谈谈对JavaScript原生拖放的深入理解
2016/09/20 Javascript
老生常谈Javascript中的原型和this指针
2016/10/09 Javascript
nodejs搭建本地服务器并访问文件的方法
2017/03/03 NodeJs
深入理解react-router@4.0 使用和源码解析
2017/05/23 Javascript
vue.js项目打包上线的图文教程
2017/11/16 Javascript
vue2.0路由切换后页面滚动位置不变BUG的解决方法
2018/03/14 Javascript
详解Vue 全局引入bass.scss 处理方案
2018/03/26 Javascript
JavaScript中call和apply方法的区别实例分析
2018/08/03 Javascript
Nodejs中怎么实现函数的串行执行
2019/03/02 NodeJs
JQuery通过键盘控制键盘按下与松开触发事件
2020/08/07 jQuery
python urllib爬取百度云连接的实例代码
2017/06/19 Python
浅谈Python中带_的变量或函数命名
2017/12/04 Python
Python打开文件,将list、numpy数组内容写入txt文件中的方法
2018/10/26 Python
django admin 根据choice字段选择的不同来显示不同的页面方式
2020/05/13 Python
基于django 的orm中非主键自增的实现方式
2020/05/18 Python
Python 虚拟环境工作原理解析
2020/12/24 Python
美国婴童服装市场上的领先品牌:Carter’s
2018/02/08 全球购物
FLOS美国官网:意大利高级照明工艺的传奇
2018/08/07 全球购物
家得宝官网:The Home Depot(全球最大的家居装饰专业零售商)
2018/12/17 全球购物
土木工程应届生求职信
2013/10/31 职场文书
户籍证明书标准模板
2014/09/10 职场文书
党员批评与自我批评总结
2014/10/15 职场文书
开展批评与自我批评发言稿
2014/10/16 职场文书
2015年小班保育员工作总结
2015/05/27 职场文书
超级礼物观后感
2015/06/15 职场文书
React Native项目框架搭建的一些心得体会
2021/05/28 Javascript
CDPR谈《巫师》新作用虚幻5原因 称不会为Epic独占
2022/04/06 其他游戏