Mysql索引失效问题如何排查 mysql的索引失效情况
wptr33 2024-12-28 15:58 26 浏览
前言:
上篇文章我们分析了慢sql如何排查,往往Mysql的索引失效是一个比较常见的问题,这种情况一般会在慢sql发生时需要考虑,考虑是否存在索引失效的问题。
在排查索引失效的时候,第一步一定是找到要分析的SQL语句,然后通过explain查看他的执行计划。主要关注type、key和extra这几个字段。
explain执行计划关键词
一个执行计划中,共有12个字段,每个字段都挺重要的,先来介绍下这12个字段
- id:执行计划中每个操作的唯一标识符。对于一条查询语句,每个操作都有一个唯一的id。但是在多表join的时候,一次explain中的多条记录的id是相同的。
- select type:操作的类型。常见的类型包括SIMPLE、PRIMARY、SUBQUERY、UNION等。不同类型的操作会影响查询的执行效率。
- table:当前操作所涉及的表。
- partitions:当前操作所涉及的分区。
- type:表示查询时所使用的索引类型,包括ALL、index、range、ref、eq ref、const等。
- possible keys:表示可能被查询优化器选择使用的索引。
- key:表示查询优化器选择使用的索引。
- key len:表示索引的长度。索引的长度越短,查询时的效率越高。
- ref:用来表示哪些列或常量被用来与key列中命名的索引进行比较。
- rows:表示此操作需要扫描的行数,即扫描表中多少行才能得到结果。
- filtered:表示此操作过滤掉的行数占扫描行数的百分比。该值越大,表示查询结果越准确。
- Extra:表示其他额外的信息,包括Usingindex、Using filesort、Using temporary等。
是否走索引分析
通过key+type+extra来判断一条SQL语句是否用到了索引。如果有用到索引,那么是走了覆盖索引呢?还是索引下推呢?还是扫描了整颗索引树呢?或者是用到了索引跳跃扫描等等。
一般来说,比较理想的走索引的话,应该是以下几种情况:
- 首先,key一定要有值,不能是NULL
- 其次,type应该是ref、eqref、range、const等这几个
- 还有,extra的话,如果是NULL,或者usingindex,usingindex condition都是可以的
如果通过执行计划之后,发现一条SQL没有走索引,比如type=ALL,key=NULL,extra= Using where。
那么就要进一步分析没有走索引的原因了。我们需要知道的是,到底要不要走索引,走哪个索引,是MySQL的优G化器决定的,他会根据预估的成本来做一个决定。
那么,有以下这么几种情况可能会导致没走索引:
- 没有正确创建索引:当查询语句中的where条件中的字段,没有创建索引,或者不符合最左前缀匹配的话,就是没有正确的创建索引。
- 引区分度不高:如果索引的区分度不够高,那么可能会不走索引,因为这种情况下走索引的效率并不高。
- 表太小:当表中的数据很小,优化器认为扫全表的成本也不高的时候,也可能不走索引
- 查询语句中,索引字段因为用到了函数、类型不一致等导致了索引失效
上述对应情况逐一分析
- 如果没有正确创建索引,那么就根据SQL语句,创建合适的索引。如果没有遵守最左前缀那么就调整一下索引或者修改SQL语句。
- 索引区分度不高的话,那么就考虑换一个索引字段。
- 表太小这种情况确实也没啥优化的必要了,用不用索引可能影响不大的
- 排查具体的失效原因,然后针对性的调整SQL语句就行了。
可能导致索引失效的情况
创建一张表(msql5.7)
CREATE TABLEmytable(
id int(11) NOT NULL AUTO INCREMENT,
name varchar(50) NOT NULL,
age int(11) DEFAULT NULL,
create time datetime DEFAULT NULL,
PRIMARY KEY (id)
UNIOUE KEY name(name),
KEY age( age),
KEY create time (create time)
)ENGINE=INnODB DEFAULT CHARSET=utf8mb4;
insert into mytable(id,name,age,create time)values(1,"cw",20,now());
insert into mytable(id,name,age,create time)values(2,"cw1",21,now());
insert into mytable(id,name,age,create time)values(3,"cw2",22,now());
insert into mytable(id,name,age,create time)values(4,"cw3",20,now());
insert into mytable(id,name,age,create time)values(5,"cw3",15,now());
insert into mytable(id,name,age,create time) values(6,"cw4",43,now());
insert into mytable(id,name,age,create time)values(7,"cw5",32,now());
insert into mytable(id,name,age,create time)values(8,"cw6",12,now());
insert into mytable(id,name,age,create time) values(9,"cw7",1,now());
insert into mytable(id,name,age,create time)values(10,"cw8",43,now());
参与索引计算
以上SQL是可以走索引的,但是如果我们在字段中增加计算的话,就会索引失效:
如何以下形式计算可以走索引
对索引列进行函数操作
以上走索引的,增加函数操作的话,就会索引失效
使用or
select * from mytable where name = 'cw' and age>18;
但是如果使用or的话,并且or两边存在<或者>的使用,就会索引失效
select * from mytable where name = 'cw' or age>18;
如果OR两边都是=判断,并且两个字段都有索引,那么也是可以走索引的,如:
select * from mytable where name = 'cw' or age=18;
like操作
select * from mytable where name like '%cw%';
select * from mytable where name like '%cw';
select * from mytable where name like 'cw%';
select * from mytable where name like 'c%w';
隐式类型转换
select * from mytable where name = 1;
以上情况,name是一个varchar类型,但是我们用int类型查询,这种是会导致索引失效的。
这种情况有一个特例,如果字段类型为int类型,而查询条件添加了单引号或双引号,则Mysql会参数转化为int类型,这种情况也能走索引:
select * from mytable where age= '1';
不等于比较
以下可能走索引的
is not null
以下情况索引失效
order by
当进行order by的时候,如果数据量很小,数据库可能会直接在内存中进行排序,而不使用索引。
in
使用in的时候,有可能走索引,也有可能不走,一般在in中的值比较少的时候可能会走索引优化,但是如果选项比较多的时候,可能会不走索引:
select * from mytable where name in ('cw');
select * from mytable where name in ('cw','hshs','cww');
总结
本篇分析了索引失效的不同情况,旨在帮忙大家在工作中快速定位自己写的sql没走索引的情况分析,更快速的解决索引失效的问题。
相关推荐
- [常用工具] git基础学习笔记_git工具有哪些
-
添加推送信息,-m=messagegitcommit-m“添加注释”查看状态...
- centos7安装部署gitlab_centos7安装git服务器
-
一、Gitlab介1.1gitlab信息GitLab是利用RubyonRails一个开源的版本管理系统,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。...
- 太高效了!玩了这么久的Linux,居然不知道这7个终端快捷键
-
作为Linux用户,大家肯定在Linux终端下敲过无数的命令。有的命令很短,比如:ls、cd、pwd之类,这种命令大家毫无压力。但是,有些命令就比较长了,比如:...
- 提高开发速度还能保证质量的10个小窍门
-
养成坏习惯真是分分钟的事儿,而养成好习惯却很难。我发现,把那些对我有用的习惯写下来,能让我坚持住已经花心思养成的好习惯。...
- 版本管理最好用的工具,你懂多少?
-
版本控制(Revisioncontrol)是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史,方便查看更改历史记录,备份以便恢复以前的版本的软件工程技术。...
- Git回退到某个版本_git回退到某个版本详细步骤
-
在开发过程,有时会遇到合并代码或者合并主分支代码导致自己分支代码冲突等问题,这时我们需要回退到某个commit_id版本1,查看所有历史版本,获取git的某个历史版本id...
- Kubernetes + Jenkins + Harbor 全景实战手册
-
Kubernetes+Jenkins+Harbor全景实战手册在现代企业级DevOps体系中,Kubernetes(K8s)、Jenkins和Harbor组成的CI/CD流水...
- git常用命令整理_git常见命令
-
一、Git仓库完整迁移完整迁移,就是指,不仅将所有代码移植到新的仓库,而且要保留所有的commit记录1.随便找个文件夹,从原地址克隆一份裸版本库...
- 第三章:Git分支管理(多人协作基础)
-
3.1分支基本概念分支是Git最强大的功能之一,它允许你在主线之外创建独立的开发线路,互不干扰。理解分支的工作原理是掌握Git的关键。核心概念:HEAD:指向当前分支的指针...
- 云效Codeup怎么创建分支并进行分支管理
-
云效Codeup怎么创建分支并进行分支管理,分支是为了将修改记录分叉备份保存,不受其他分支的影响,所以在同一个代码库里可以同时进行多个修改。创建仓库时,会自动创建Master分支作为默认分支,后续...
- git 如何删除本地和远程分支?_git怎么删除远程仓库
-
Git分支对于开发人员来说是一项强大的功能,但要维护干净的存储库,就需要知道如何删除过时的分支。本指南涵盖了您需要了解的有关本地和远程删除Git分支的所有信息。了解Git分支...
- git 实现一份代码push到两个git地址上
-
一直以来想把自己的博客代码托管到github和coding上想一次更改一次push两个地址一起更新今天有空查资料实践了下本博客的github地址coding的git地址如果是Gi...
- git操作:cherry-pick和rebase_git cherry-pick bad object
-
在编码中经常涉及到分支之间的代码同步问题,那就需要cherry-pick和rebase命令问题:如何将某个分支的多个commit合并到另一个分支,并在另一个分支只保留一个commit记录解答:假设有两...
- 模型文件硬塞进 Git,GitHub 直接打回原形:使用Git-LFS管理大文件
-
前言最近接手了一个计算机视觉项目代码是屎山就不说了,反正我也不看代码主要就是构建一下docker镜像,测试一下部署的兼容性这本来不难但是,国内服务器的网络环境实在是恶劣,需要配置各种镜像(dock...
- 防弹少年团田柾国《Euphoria》2周年 获世界实时趋势榜1位 恭喜呀
-
当天韩国时间凌晨3时左右,该曲在Twitter上以“2YearsWithEuphoria”的HashTag登上了世界趋势1位。在韩国推特实时趋势中,从上午开始到现在“Euphoria2岁”的Has...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
程序员的开源月刊《HelloGitHub》第 71 期
-
详细介绍一下Redis的Watch机制,可以利用Watch机制来做什么?
-
假如有100W个用户抢一张票,除了负载均衡办法,怎么支持高并发?
-
Java面试必考问题:什么是乐观锁与悲观锁
-
如何将AI助手接入微信(打开ai手机助手)
-
SparkSQL——DataFrame的创建与使用
-
redission YYDS spring boot redission 使用
-
一文带你了解Redis与Memcached? redis与memcached的区别
-
如何利用Redis进行事务处理呢? 如何利用redis进行事务处理呢英文
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)