mysql 索引十连问| 剑指 offer - mysql
以下是结合网上及此前面试时遇到的一些关于mysql索引的面试题。
若对mysql索引不太了解可先翻阅相关文章
什么是索引?
索引类似书本的目录,查询书中的指定内容时,先在目录上查找,之后可快速定位到内容位置。在数据库中通常通过B树/B+树数据结构实现。
主键索引和非主键索引有什么区别?
主键索引树中叶子节点存储的是整行数据,而非主键索引叶子节点上保存的是主键的值。使用非主键索引时,先从非主键索引获取到行对应主键ID,之后再根据id在主键索引树上搜索对应行数据,这个过程也被称为回表。
一般使用什么字段作为主键,为什么?
一般使用innodb的自增整数类型作为主键:
- 因为自增,容易保证主键索引的有序性,同时还能避免新数据中间位置插入时导致的页分裂;
- 二级索引叶子节点上保存的是主键值,整数类型主键长度较小,二级索引树占用的空间较小。
索引使用场景
where
为查询条件字段创建索引,以达到快速过滤指定条件数据的目的。
order by
当使用order by将查询结果按某个字段排序时,可考虑为该字段创建索引。没有索引时,会先将查询结果放到内存中进行排序(若内存空间不足,会利用磁盘辅助排序),比较影响查询效率。
索引本身是有序的,可以直接按索引的顺序逐条回表取出数据即可。如果是分页查询,效果更好,这时候只需要取出某个范围的索引对应的数据,而不需要取出所有满足条件的数据排序后再截取返回分页数据。
join
使用join时,为被驱动表的关联字段创建索引,可以有效提高查询效率。比如select * from t1 straight_join t2 on (t1.a=t2.a) where t1.b = 'xxxx'; t2的字段a上有索引,查询过程会是先从表1中依次取出满足条件的行数据,之后用行数据中的a字段去t2上匹配后将两表字段拼接返回,此时能使用到t2.a的索引,避免了t2全表扫描。
索引覆盖
如果select字段+where字段字段列数不太多且查询频繁时,可以考虑为select和where字段创建联合索引,避免查询时回表,提高查询效率。比如select a from t where b = ‘xx’, 创建联合索引(b, a), 此时扫描索引树后,就已经得到需要查询的字段a了,不需要再回表。需要注意的是联合索引字段的顺序,这个语句无法使用到索引(a, b)。
创建索引需要注意的地方
最左前缀匹配原则,联合索引需要注意索引字段的顺序,mysql 会一直向右匹配直到遇到范围查询 (>、<、between、like) 就停止匹配,比如
a = 1 and b = 2 and c > 3 and d = 4,如果建立 (a,b,c,d) 顺序的索引,d 是用不到索引的。
字段是否用到索引的意思是字段是否能利用字段在索引中的有序性进行快速过滤。索引(a,b,c,d), 在索引树上是先按a进行排序,再按b进行排序,以此类推,排序规则类似order by a,b,c,d。上面查询条件中,a定值,b是有序的;b定值,c是有序的;c范围查询,剩下的d是无序的。所以d无法使用到该索引。基数小,区分度低的不适合创建索引。比如性别,最多基数最多总共就3个,此时索引过滤性能不高,查完索引后还需回表,可能比直接全表扫描效率更低。
更新频繁的字段创建索引时要权衡索引维护成本。
尽量扩展索引,比如已经有a索引,现在要加 (a,b) 的索引,那么只需要修改原来的索引即可。
避免对text大字段创建索引,会导致索引树太大,查询效率不高。如果大字段前n个字符区分度较高,可以考虑创建前缀索引,只索引开始的部分字符,这样可以节约索引空间,提高索引效率。其缺点是不能用于ORDER BY和GROUP BY操作,也不能用于覆盖索引(因为前缀索引树上只有字段的部分内容,需要进行回表)。
什么时候索引会失效?
模糊查询时查询条件以”%”开头无法使用到索引
使用or查询时,只有当所有的查询条件字段都有索引才能使用到,比如
a=1 or b = 2,只有当a和b都有索引才能使用到索引。数据类型出现隐式转换,如varchar不加单引号的时候可能会自动转换为int类型,这个时候索引失效。
在索引列上使用IS NULL或者 IS NOT NULL 时候,索引失效,因为索引不会索引空值。
在索引字段上使用”NOT、 <>、!=、NOT IN “时是不会使用索引的,这时只会进行全表扫描。
对索引字段进行计算操作,函数操作时不会使用索引。
当优化器觉得全表扫描速度比索引速度快的时候不会使用索引。一般出现在全表数据比较少的情况下,这时全表扫描比在非主键索引上查找后再回表速度可能更快。
联合索引时,查找不满足最左匹配规则,无法使用到联合索引。
innodb使用b+树作为索引模型的原因
Mysql设计的使用场景比较广泛,需要对遍历查询、单条查询、数据更新都需要较好的性能支持。B+树的特性是只在叶子节点上存储数据。可以从数据读写方面与哈希表、有序数组、b树其他几种索引模型进行比较:
- 哈希表:哈希表只能进行等值查询,在处理范围查询和排序查询时,需要全表扫描哈希表。
- 有序数组:有序数组在进行数据更新时成本较大。往数组中间位置添加数据时,需要移动后面的数据位置。
- B树:b树在非叶子节点上也存储数据,在遍历数据时,需要对不同层级的节点上的数据进行拼接和排序,这会导致多次磁盘io。查询效率较低。
如何删除百万级别或以上的数据?
可以考虑先删掉表的索引,等删除数据后再重建索引。当我们在进行数据修改时,需要同时修改索引,这些额外的索引维护成本较低数据修改的效率;同时,大量的数据删除会导致索引数据页产生大量的碎片空间,此时删除数据后重建索引可以使索引树更“紧凑”,提高磁盘空间利用率。
Innodb中的B+树模型中,N叉树的N能否被修改?
通过调整索引字段大小来修改
N 叉树中非叶子节点存放的是索引信息,索引包含 Key 和 Point 指针。Point 指针固定为 6 个字节,假如 Key 为 10 个字节,那么单个索引就是 16 个字节。如果 B + 树中页大小为 16 K,那么一个页就可以存储 1024 个索引,此时 N 就等于 1024。我们通过改变 Key 的大小,就可以改变 N 的值。通过修改页大小间接修改,页越大,每页存放的索引数量就越多,N就越大。
数据页调整后,如果数据页太小层数会太深,数据页太大,加载到内存的时间和单个数据页查询时间会提高,需要达到平衡才行。
如何知道语句有没有走索引查询?
可以利用 explain 查看 sql 语句的执行计划,通过执行计划来分析索引使用情况。
写在最后
喜欢本文的朋友,欢迎关注公众号「会玩 code」,专注大白话分享实用技术。

公众号福利
回复【mysql】获取免费测试数据库!!
回复【pdf】获取持续更新海量学习资料!!
mysql 索引十连问| 剑指 offer - mysql的更多相关文章
- 剑指Offer(十八):二叉树的镜像
剑指Offer(十八):二叉树的镜像 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/baidu ...
- 剑指Offer(十九):顺时针打印矩阵
剑指Offer(十九):顺时针打印矩阵 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/baid ...
- 剑指Offer(二十二):从上往下打印二叉树
剑指Offer(二十二):从上往下打印二叉树 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/b ...
- 剑指Offer(二十五):复杂链表的复制
剑指Offer(二十五):复杂链表的复制 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/bai ...
- 剑指Offer(二十六):二叉搜索树与双向链表
剑指Offer(二十六):二叉搜索树与双向链表 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/ ...
- 剑指Offer(二十八):数组中出现次数超过一半的数字
剑指Offer(二十八):数组中出现次数超过一半的数字 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn. ...
- 剑指Offer(三十二):把数组排成最小的数
剑指Offer(三十二):把数组排成最小的数 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/b ...
- 剑指Offer(二十):包含min函数的栈
剑指Offer(二十):包含min函数的栈 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/ba ...
- 剑指Offer(三十六):两个链表的第一个公共结点
剑指Offer(三十六):两个链表的第一个公共结点 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.ne ...
随机推荐
- 力扣 - 208. 实现Trie(前缀树)
目录 题目 思路 代码 复杂度分析 题目 208. 实现 Trie (前缀树) 思路 在我们生活中很多地方都用到了前缀树:自动补全,模糊匹配,九宫格打字预测等等... 虽然说用哈希表也可以实现:是否出 ...
- 数据表设计之主键自增、UUID或联合主键
最近在做数据库设计的时候(以MySQL为主),遇到不少困惑,因为之前做数据库表设计,基本上主键都是使用自增的形式,最近因为这种做法,被领导指出存在一些不足,于是我想搞明白哪里不足. 一.MySQL为什 ...
- kiali的服务降级和暗隐的有关问题
记录两个问题 1. 服务在kiali的Applications 和 Workloads 显示为降级状态 2. 服务已经删除后在kiali的 Graph 显示依然存在 前言 istio部署到预发集群后, ...
- Golang+Protobuf+PixieJS 开发 Web 多人在线射击游戏(原创翻译)
简介 Superstellar 是一款开源的多人 Web 太空游戏,非常适合入门 Golang 游戏服务器开发. 规则很简单:摧毁移动的物体,不要被其他玩家和小行星杀死.你拥有两种资源 - 生命值(h ...
- python基础(〇):注释
单行注释 Python中单行注释以 # 开头,例如: # 这是一个注释1 print("Hello, World!") # 这是一个注释2 多行注释 单引号(''') ''' 这是 ...
- 「Unity卡牌自走棋」项目NABCD分析
项目 内容 这个作业属于哪个课程 2021学年春季软件工程(罗杰 任健) 这个作业的要求在哪里 团队项目-初次邂逅,需求分析 在这个课程的目标是 锻炼在大规模开发中的团队协作能力 这个作业在哪个具体方 ...
- Hibernate(十四篇)
(一)Hibernate简介 (二)hibernate配置管理 (三)Hibernate对象-关系映射文件 (四)Hibernate API详解 (五)Hibernate一级缓存 (六)Hiberna ...
- Ubuntu安装docker/docker-compose(在全新系统状态下的安装)
设置仓库 更新 apt 包索引. $ sudo apt-get update 安装 apt 依赖包,用于通过HTTPS来获取仓库: $ sudo apt-get install \ apt-trans ...
- MySQL数据库高级一:架构介绍
两天半就可以 严禁使用 精通 在简历上 了解的越多,越比他人有优势 linux的mysql需要使用中文字符集那么就要修改配置文件 1.mysql的linux版 安装和卸载不说了 2.逻辑架构 总体概况 ...
- 腾讯云TCA开发工程师认证考试
1.关于云硬盘CBS的描述,错误的是哪一项?(B) A.云硬盘提供数据块级别的数据存储,采用三副本的分布式机制,为 CVM 提供数据可靠性保证 B.云硬盘可在同一可用区中自由挂载.卸载;挂载和卸载过程 ...