面试官:聊一下你对MySQL索引的理解?

作者:浪人

来源:http://t.cn/AiKmcEef

MySQL索引?这玩意儿还能简单聊?明显是在挖坑,幸好老夫早有准备,切听我一一道来。 

一、索引是什么?

索引是帮助MySQL高效获取数据的数据结构。


二、索引能干什么?

索引非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要。索引能够轻易将查询性能提高好几个数量级,总的来说就是可以明显的提高查询效率。


三、索引的分类?

1、从存储结构上来划分:BTree索引(B-Tree或B+Tree索引),Hash索引,full-index全文索引,R-Tree索引。这里所描述的是索引存储时保存的形式,

2、从应用层次来分:普通索引,唯一索引,复合索引

3、根据中数据的物理顺序与键值的逻辑(索引)顺序关系:聚集索引,非聚集索引。

平时讲的索引类型一般是指在应用层次的划分。

就像手机分类:安卓手机,IOS手机 与 华为手机,苹果手机,OPPO手机一样。

普通索引即一个索引只包含单个列,一个表可以有多个单列索引

唯一索引索引列的值必须唯一,但允许有空值

复合索引多列值组成一个索引,专门用于组合搜索,其效率大于索引合并

聚簇索引(聚集索引)并不是一种单独的索引类型,而是一种数据存储方式。具体细节取决于不同的实现,InnoDB的聚簇索引其实就是在同一个结构中保存了B-Tree索引(技术上来说是B+Tree)和数据行。

非聚簇索引不是聚簇索引,就是非聚簇索引

四、索引的底层实现

mysql默认存储引擎innodb只显式支持B-Tree( 从技术上来说是B+Tree)索引,对于频繁访问的表,innodb会透明建立自适应hash索引,即在B树索引基础上建立hash索引,可以显著提高查找效率,对于客户端是透明的,不可控制的,隐式的。

不谈存储引擎,只讨论实现(抽象)

Hash索引

基于哈希表实现,只有精确匹配索引所有列的查询才有效,对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码(hash code),并且Hash索引将所有的哈希码存储在索引中,同时在索引表中保存指向每个数据行的指针。

B-Tree索引(MySQL使用B+Tree)

B-Tree能加快数据的访问速度,因为存储引擎不再需要进行全表扫描来获取数据,数据分布在各个节点之中。

B+Tree索引

是B-Tree的改进版本,同时也是数据库索引索引所采用的存储结构。数据都在叶子节点上,并且增加了顺序访问指针,每个叶子节点都指向相邻的叶子节点的地址。相比B-Tree来说,进行范围查找时只需要查找两个节点,进行遍历即可。而B-Tree需要获取所有节点,相比之下B+Tree效率更高。

结合存储引擎来讨论(一般默认使用B+Tree)

案例:假设有一张学生表,id为主键

idnamebirthday
1Tom1996-01-01
2Jann1996-01-04
3Ray1996-01-08
4Michael1996-01-10
5Jack1996-01-13
6Steven1996-01-23
7Lily1996-01-25

在MyISAM引擎中的实现(二级索引也是这样实现的)

在InnoDB中的实现


五、为什么索引结构默认使用B+Tree,而不是Hash,二叉树,红黑树?

B-tree:因为B树不管叶子节点还是非叶子节点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少(有些资料也称为扇出),指针少的情况下要保存大量数据,只能增加树的高度,导致IO操作变多,查询性能变低;

Hash:虽然可以快速定位,但是没有顺序,IO复杂度高。

二叉树:树的高度不均匀,不能自平衡,查找效率跟数据有关(树的高度),并且IO代价高。

红黑树:树的高度随着数据量增加而增加,IO代价高。


六、为什么官方建议使用自增长主键作为索引?

结合B+Tree的特点,自增主键是连续的,在插入过程中尽量减少页分裂,即使要进行页分裂,也只会分裂很少一部分。并且能减少数据的移动,每次插入都是插入到最后。总之就是减少分裂和移动的频率。

插入连续的数据:

插入非连续的数据

七、总结

  1. MySQL使用B+Tree作为索引数据结构。

  2. B+Tree在新增数据时,会根据索引指定列的值对旧的B+Tree做调整。

  3. 从物理存储结构上说,B-Tree和B+Tree都以页(4K)来划分节点的大小,但是由于B+Tree中中间节点不存储数据,因此B+Tree能够在同样大小的节点中,存储更多的key,提高查找效率。

  4. 影响MySQL查找性能的主要还是磁盘IO次数,大部分是磁头移动到指定磁道的时间花费。

  5. MyISAM存储引擎下索引和数据存储是分离的,InnoDB索引和数据存储在一起。

  6. InnoDB存储引擎下索引的实现,(辅助索引)全部是依赖于主索引建立的(辅助索引中叶子结点存储的并不是数据的地址,还是主索引的值,因此,所有依赖于辅助索引的都是先根据辅助索引查到主索引,再根据主索引查数据的地址)。

  7. 由于InnoDB索引的特性,因此如果主索引不是自增的(id作主键),那么每次插入新的数据,都很可能对B+Tree的主索引进行重整,影响性能。因此,尽量以自增id作为InnoDB的主索引。


【END】

关注下方二维码,订阅更多精彩内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/546499.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux新建用户可以在shell中切换到该用户也能登录到图形桌面

解决使用useradd testname,passwd testname命令确实创建了一个用户,可以在shell中切换到该用户。但不能登录到图形桌面的问题! 通过下面方法可以在Linux中新建用户,并创建用户主目录,也能登录到图形桌面 1.普通用户先…

这样写Java,同事直呼666

作者:涛姐涛哥来源:cnblogs.com/taojietaoge/p/11575376.html一、MyBatis 不要写 11当遇到多个查询条件,使用where 11 可以很方便的解决我们的问题,但是这样很可能会造成非常大的性能损失,因为添加了 “where 11 ”的过…

Lync Server 2010 安装部署系列三:添加DNS记录

为了让客户端能够自动登录系统,我们需要在DNS服务器上设置创建相关的SRV记录,首先在DNS服务器上创建一条A记录pool.Contoso.com对应IP地址为192.168.1.11,然后创建一条SRV记录对应刚才创建的A记录,服务的内容为_sipinternaltls&am…

Linux系统下MySQL导出数据库和导入数据库的命令

一、MySQL导出数据库用mysqldump命令 注意mysql的安装路径,即此命令的路径,如果你只要查询mysql的运行文件所在地址,直接用下面的命令就可以了,再切换到mysql的运行文件的路径 which mysqlcd /usr/bin/1、导出数据和表结构 命令格…

工作中 99% 会用到的 Git 命令

作者:命中水来源:https://www.cxiansheng.cn/daily/4901.分支操作git branch 创建分支git branch -b 创建并切换到新建的分支上git checkout 切换分支git branch 查看分支列表git branch -v 查看所有分支的最后一次操作git branch -vv 查看当前分支git b…

JSP tomcat 更新不生效

2019独角兽企业重金招聘Python工程师标准>>> 今天遇到一问题,更改好的jsp部署到tomcat后,无论如何页面也不生效,最后才知道是tomcat的work目录没有清的原因,借此机会也特地看了下work目录的作用以及原理,做…

Win10专业版系统Docker安装、配置和使用详细教程

一、win10专业版系统首先需要开启硬件虚拟化及Hyper-V功能,才能进行Docker for Windows软件安装。 如何开启硬件虚拟化,自行百度。可在任务栏中查看虚拟化是否开启。 win10系统,打开控制面板-“应用”-“程序和功能”,开启Hyper…

框架开发之Java注解的妙用

作者:locality来源:https://www.jianshu.com/p/b560b30726d4如果你还不会使用注解,你肯定不好意思对别人说你学过Spring,你学过Mybatis,因为它们用了大量的注解。可见注解在开发领域已经使用的非常广泛了。注解的好处&…

Win10专业版系统PyCharm专业版使用WSL(ubuntu20.04 LTS)配置Docker解释器配置环境详细教程

提前准备好环境: Win10x64专业版21H2; WSL的ubuntu20.04系统; PyCharm2020专业版; Docker for Windows软件稳定版。 一、Win10系统安装WSL(ubuntu20.04 LTS)子系统 1.按照下图,开启“适用于Linux的Windows子系统”和“虚拟机平台”功能,按照提示重启计算机。 2.在Mic…

Mybatis:颠覆你心中对事务的理解

作者:祖大俊来源:my.oschina.net/zudajun/blog/6667641.说到数据库事务,人们脑海里自然不自然的就会浮现出事务的四大特性、四大隔离级别、七大传播特性。四大还好说,问题是七大传播特性是哪儿来的?是Spring在当前线程…

Docker镜像和容器常用命令

一、.Docker帮助命令 1.显示docker的版本信息 docker version 2.显示docker的系统信息,包括镜像和容器的数量 docker info3.docker帮助命令 docker 命令 --help二、Docker镜像命令 1.查看所有本地的主机上的镜像 docker images实例测试: 2.搜索镜像…

如何学会阅读源码?

作者 | youzhibing链接 | cnblogs.com/youzhibing/p/9553752.html1.读源码的经历刚参加工作那会,没想过去读源码,更没想过去改框架的源码;总想着别人的框架应该是完美的、万能的,应该不需要改;另外即使我改了源码&…

求模和求余

一直以为求模和求余是一回事,发现这两者是不同的。以下为网上转载的资料: 通常情况下取模运算(mod)和求余(rem)运算被混为一谈,因为在大多数的编程语言里,都用%符号表示取模或者求余运算。在这里要提醒大家要十分注意当前环境下%运…

利用Dockefile将Python的py文件项目代码打包为Docker镜像

1.创建python项目 【备注:一定要将项目python环境依赖存至本项目下,默认依赖本机python环境(会造成依赖包过多)】 2.创建main.py文件,完成程序代码 主要功能就是获取"https://www.hao123.com/"网址页面源代码,并存储…

面试官:如何实现幂等性校验?

作者 | wangzaiplus来源 | https://www.jianshu.com/p/6189275403ed一、概念幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次比如:订单接口, 不能多次创建订单支付接口, 重复支付同一笔订单只能扣一次钱支付宝回调接口, 可能会多次回调, 必须处理…

阿里为什么禁用Executors创建线程池?

作者 | 何甜甜在吗来源 | http://rrd.me/eUh6V看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,通过源码分析禁用的原因。写在前面首先感谢大家在盖楼的间隙阅读本篇文章&#xff0…

Debian11镜像更新为阿里巴巴开源镜像站镜像,切换root用户,解决用户名不在sudoers文件中此事将被报告,Debian11 文件夹对话框、火狐浏览器、命令终端等没有最大化和最小化

选择Debian作为编程开发最佳Linux的理由: Debian是面向程序员的最古老,最出色的Linux发行版之一。Debian提供了具有.deb软件包管理兼容性的超稳定发行版。Debian为程序员提供了许多最新功能。因此,它具有一个特殊的编程空间。Debian是开发人员…

SCCM2012R2部署之四:配置客户端发现

前面3个章节我们简单的,介绍了安装配置和相关的组件。接下来我们需要给大家介绍的是如何配置客户端发现,让SCCM能真正管控到AD中的所有终端,来提供IT运维的效率。首先我们打开SCCM控制台,如图4-1,这就是我们安装完SCCM…

Debian11安装VLC Media Player视频播放器

在终端内执行下面命令: sudo apt install vlc

面试官:使用SpringBoot如何开发邮件发送系统?

作者 | yizhiwazi来源 | www.jianshu.com/p/5eb000544dd7SpringBoot 开发邮件发送系统还是比较方便的,在开始之前我们先来了解一下和发送邮件有关的基础知识。基础知识什么是SMTP?SMTP全称为Simple Mail Transfer Protocol(简单邮件传输协议&…