mysql 前索引_MySQL查询性能优化前,必须先掌握MySQL索引理论

数据库索引在平时的工作是必备的,怎么建好索引,怎么使用索引,可以提高数据的查询效率。而且在面试过程,数据库的索引也是必问的知识点,比如:

索引底层结构选型,那为什么选择B+树?

不同存储引擎的索引的体现形式有哪些?

索引的类型

组合索引存储方式

查询方式

最左前缀匹配原则

覆盖索引是什么?

看着这些,能说出多少,理解多少呢?因此我们需要去探究其内在原理。

636408a397f7a23bf76f9d18e854e830.png

那索引是什么?

索引的目的为了加速检索数据而设计的一种分散存储(索引常常很大,属于硬盘级的东西,所以是分散存储)的数据结构,其原理以空间换时间。

快速检索的实现的本质是数据结构,通过不同数据结构的选择,实现各种数据快速检索,索引有哈希索引和B+树索引。

索引底层结构选型,那为什么选择B+树?

数据库索引底层选型归根到底就是为提高检索效率,那么就需要考虑几个问题:

算法时间复杂度

是否存在排序

磁盘IO与预读

NOTE: 考虑到磁盘IO是非常高昂的操作,计算机操作系统做了一些优化,当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。每一次IO读取的数据我们称之为一页(page)。

哈希表( Hash Table,散列表 )

哈希表是根据键(Key)而直接访问在内存存储位置的数据结构。

ec7a7e0a694049966b8bf485eac83004.png

通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。虽然查询时间复杂度为O(1),但存在着碰撞问题,最坏情况会导致时间复杂急剧增加;

而且哈希表其只适合精准key(等于)检索,不适合范围式检索,范围检索就需要一次把所有数据找出来加载到内存,没有效率,因此不适合Mysql的底层索引的数据结构。

普通的二叉查找树

为了优化高效范围查询,且时间复杂度小,引入二叉查找树

bdc08ef5ccb151c697cc006aeeb93fbb.png

二叉查找树的时间复杂度是 O(lgn),由于数据已排序好了,所以范围查询是可以高效查询,

但会存在的问题:左右子节点的深度可能相差很大,最极端的情况只有左子树或者右子树,此时查找的效率为O(n),检索性能急剧下降,因此也不适合Mysql的底层索引的数据结构。

d371e6203860d50bed25f32725b02cec.png

平衡二叉树(AVL树)

为了优化二叉树左右子树深度相差太大的问题,我们引入了平衡二叉树,即左右子节点的深度差不超过1,平衡二叉树看来好像适合,实现了:

范围查找、数据排序

查询性能良好O(logn)

4eed859ed8141d6aafb8112ffd68cc51.png

NOTE:上图中一个磁盘块,代表硬盘上的一个存储位置

但是我们还有一个最重要因素需要考虑,磁盘IO与预读,且数据库查询数据的瓶颈在于磁盘 IO,使用平衡二叉树根据索引进行查找时,每读一个磁盘块就进行一次IO,这样没有实现计算机的预读能力,导致检索效率下降,总结出平衡二叉树作为索引的问题

太深了(即它只有二条路),深度越大进行的IO操作也就越多

太小了,每一次IO才查询磁盘块这么一点数据,太浪费IO了。操作系统规定一次IO最小4K,Mysql一次IO 16K,而图上的磁盘块能明显达不到4K

B+树

为了优化磁盘IO和预读,减少IO操作,条路太少了,那么换成多条路,那么会想到使用B树和B+树,但B树每个节点限制最多存储两个 key,也会造成IO操作过于频繁,因此优化思路为:尽可能在一次磁盘 IO 中多读一点数据到内存,那么B+树也该出场:

B+树一个节点能存很多索引,且只有B+树叶子节点存储数据

相邻节点之间有一些前驱后继关系

叶子节点是顺序排列的

d4d642fd079e4d9ace9d9e8d50419a42.png

相对于B树,B+树的优势有:

B+树扫库扫表的能力更强

B树的数据是存放在每一个节点中的,节点所在的物理地址又是随机的,所以扫表的话,进行的是随机IO

B+树的数据是存放在叶子节点的,且在一个叶子节点中的数据是连续的,所以扫表的话,进行的相对的顺序IO

B+树的磁盘读写能力更强,枝节点不保存数据,而保存更多的关键字。一次IO就能读出更多的关键字

B+树的排序能力更强,B+树的叶子节点存储的数据是已经排好序的

索引的体现形式

索引在不同的存储引擎中体现形式步一样, 最常见的是:

Innodb 引擎中体现为聚集索引方式 (索引和数据是存放在同一个文件的)

Myisam引擎中体现为非聚集索引方式 (索引和数据是存放在两个文件中的)

聚集索引方式(InnoDB存储引擎)

InnoDB存储引擎中,索引和数据是存放在同一个文件的,属于聚集索引 。而且InnoDB会自动建立好主键 ID 索引树, 因此建表时要求必须指定主键的原因。

其中,主键索引(聚集索引)的叶子节点记录了数据,而不是数据的物理地址。辅助索引的叶子节点存放的是主键key。所以当利用辅助索引查找数据时,实际上查了两遍索引(辅助索引和主键索引):

先查询辅助索引树找出主键

然后在主键索引树中根据主键查询数据

93fde4481e1ea3b3e70b68f8769aff3d.png

非聚集索引方式(Myisam存储引擎)

Myisam存储引擎中,索引和数据是存放在两个文件中的,属于非聚集索引 。不管是主键索引还是辅助索引,其叶子节点都是记录了数据的物理地址。

e0796f70b5d0c6700099b87d7662422a.png

MySQL的索引类型

MySQL索引可以分为:

普通索引(index): 加速查找

唯一索引:

主键索引:primary key :加速查找+约束(不为空且唯一)

唯一索引:unique:加速查找+约束 (唯一)

联合索引:

primary key(id,name):联合主键索引

unique(id,name):联合唯一索引

index(id,name):联合普通索引

全文索引full text :用于搜索很长一篇文章的时候,效果最好。

其中,主要理解一下联合索引的问题,存储结构,查询方式。

联合索引

联合索引,多个列组成的索引叫做联合索引,单列索引是特殊的联合索引。其存储结构如下:

1366fc2bc0cb442f47866a477b759340.png

对于联合索引来说其存储结构只不过比单值索引多了几列,组合索引列数据都记录在索引树上,(不同的组合索引,B+树也是不同的),且存储引擎会首先根据第一个索引列排序后,其他列再依次将相等值的进行排序。

NOTE:叶节点第一排,按顺序排序好,第二列,会基于第一列排序好的,将第一列相等的再下一列再排序,依次类推。

联合索引查询方式,存储引擎首先从根节点(一般常驻内存)开始查找,然后再依次在其他列中查询,直到找到该索引下的data元素即ID值,再从主键索引树上找到最终数据。

而且联合索引其选择的原则:

最左前缀匹配原则(经常使用的列优先)

离散度高的列优先

宽度小的列优先

最左前缀匹配原则

最左前缀匹配原则和联合索引的索引构建方式及存储结构是有关系的。根据上述理解分析,可以得出联合索引只能从多列索引的第一列开始查找索引才会生效,比如:

假设表user上有个联合索引(a,b,c),那么 select * from user where b = 1 and c = 2将不会命中索引

原因是联合索引的是存储引擎先按第一个字段排序,再按第二个字段排序,依次排序。

离散度

当索引中的一列离散度过低时,优化器可能直接不走索引,离散度计算方法:

离散度 = 列中不重复的数据量 / 这一列的总数据量

覆盖索引

如果一个索引包含(或覆盖)所有需要查询的字段的值,称为覆盖索,即只需扫描索引而无须回表查询 。覆盖索引可减少数据库IO,将随机IO变为顺序IO,可提高查询性能。

对于InnoDB辅助索引在叶子节点中保存了行的主键值,所以如果辅助索引(包括联合索引)能够覆盖查询,则可以避免对主键索引的二次查询。比如:

--创建联合索引

createindexname_phone_idxonuser(name,phoneNum);

--此时是覆盖索引,原因是根据name来查,命中索引name_phone_idx,

--其关键字为name,phoneNum,本身就已经包含了查询的列。

selectname,phoneNumwherename="张三";

--如果id为主键的话,此时也称作覆盖索引,原因:辅助索引的叶子节点存的就是主键

selectid,name,phoneNumwherename="张三";

总结

MySQL的索引有很多知识点要掌握,已学习了索引的底层存储结构,不同存储引擎中的索引体现,以及索引类型的基础原理知识分析,可以为后续的数据库优化提供理论知识的支撑,也会更好的理解优化方案。

【编辑推荐】

【责任编辑:未丽燕 TEL:(010)68476606】

点赞 0

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

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

相关文章

计算机维护系统Win8PE,win8如何进入PE重装电脑系统

电脑进入PE系统有很多种办法,但是最简单的莫过于本地模式。通过韩博士中的本地模式功能下载PE镜像文件,就可以直接进入到PE桌面进行电脑系统重装。如果你不信,就跟着下面的流程走一次。小编有话说:大家在打开韩博士装机大师软件之…

电子科技大学 高级计算机结构,电子科技大学计算机系统结构作业答案

电子科技大学计算机系统结构作业答案 (26页)本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦!1.90 积分查看考卷——作业提交1 当前得分:5 分(总分:100 分),折合成百分…

测试手机速度的软件叫什么,手机测网速哪个软件好? 精确测速软件推荐

随着智能手机的普及,现在人们几乎已经人手一部手机。4G网络在我国已经非常的普及了,但是我们在使用手机时时常还是会发现会出现断网的情况,严重的影响了我们的工作以及上网体验,特别是在我们看视频或者打游戏时断网,更…

python在末尾加关闭程序_廖雪峰的Python教程教程-02

廖雪峰的Python教程:Python教程​www.liaoxuefeng.com廖老师的小结:1) list[],一种有序的集合:用len()函数可以获得list元素的个数;索引是从0开始,最后一个元素的索引是len(list)-1;list.append…

sensei鼠标测试软件,'黑科技'传感器打造出的FPS利器 - 赛睿Sensei 310 鼠标

黑科技传感器打造出的FPS利器 - 赛睿Sensei 310 鼠标2018-03-12 10:00:0010点赞13收藏20评论*级电竞外设品牌SteelSeries赛睿2017年在鼠标领域依靠Rival系列攻城掠地, 从低到高都有覆盖,但Rival系列全系都是右手的人体工学设计,对于喜欢对称设计的玩家来…

汉字计算机编码是谁发明的,神奇的汉字编码,了解一下

一直觉得不是由中国人发明的计算机,却可以使用汉字进行界面交互非常神奇。今天就来和大家聊一下关于汉字编码的最底层的逻辑。(1)汉字信息交换码(国标码)汉字交换码是指不同的具有汉字处理功能的计算机系统之间在交换汉字信息时所使用的代码标准。国家标准GB2312-80…

怎么把foxmail的邮件和服务器同步,foxmail设置ActiveSync同步功能怎么操作?设置ActiveSync同步功能方法介绍...

foxmail设置ActiveSync同步功能的操作常常困扰着不少用户,下面笔者就分享了foxmail设置ActiveSync同步功能的操作方法,不懂的朋友一起来看看吧。foxmail设置ActiveSync同步功能的操作方法一、开启和关闭"ActiveSync同步"功能的操作对新建QQMai…

php页面不断弹出值_电脑自动弹出网页怎么办

电脑自动弹出网页的解决方法:我们可以利用360安全卫士中的弹窗过滤工具来解决此问题。首先我们打开360安全卫士;然后找到弹窗过滤工具;最后选择【强力模式】,保存设置即可。电脑自动弹出网页可以使用360安全卫士来进行弹窗拦截。打…

css怎样使弹跳的小球旋转,如何使用纯CSS实现小球跳跃台阶的动画效果(附源码)...

本篇文章给大家带来的内容是关于如何使用纯CSS实现小球跳跃台阶的动画效果(附源码) ,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。效果预览源代码下载https://github.com/comehope/front-end-daily-challenges代码解读定义…

怎么把4399小游戏的代码_25行代码带你爬取4399小游戏数据,看下童年的游戏是否还在...

前言本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理。还记得童年的网页小游戏吗?今天带大家爬取4399小游戏网站的数据,游戏名字链接地址目标网站http://www.4399.com/基本环境配置python 3.6pycharm…

如何使mysql编码格式_Mysql设置编码方式及基本操作

介绍Mysql 默认安装后的编码方式默认一般是Latin, 在插入汉字数据或读取的时候,存在乱码或报错。这时候,只需要修改编码方式为UTF8,统一数据库和数据表的编码方式。如何修改1、 复制MySQL数据库中的配置文件,然后粘贴重命名为my.i…

ftp服务器复制粘贴文件夹,ftp服务器复制粘贴文件夹

ftp服务器复制粘贴文件夹 内容精选换一换下载地址:https://varnish-cache.org/_downloads/varnish-6.2.0.tgz若服务器可以访问网络,则可以直接在服务器上使用wget命令下载源码。--prefixPATH:指定Varnish的安装目录。HSS默认会将防护目录下的…

怎么把项目的数据上传到服务器,怎么把sql数据库上传到云服务器

怎么把sql数据库上传到云服务器 内容精选换一换本章介绍如何在管理控制台购买GaussDB(for openGauss)实例,并通过内网使用弹性云服务器连接GaussDB(for openGauss)实例。GaussDB(for openGauss)提供gsql工具帮助您在命令行下连接数据库,您需要提前创建一…

微信无连接服务器1.104,微信成语猜猜看太子少师答案汇总 太子少师1-104关攻略...

本文导航第1页: 太子少师第8页:翰林第2页:学童第9页:侍郎第3页:童生第10页:尚书第4页:秀才第11页:大学士第5页:举人第12页:御史第6页:贡士第13页&…

java微博开发_【新手入门篇】新浪微博应用开发之Java入门篇

新浪微博应用开发之Java篇2012年11月11日星期日一、开发流程简介:2、 在以下地址创建一个应用,假设创建一个桌面应用:3、 进入管理中心,查看并记住应用ID和密码:4、 在“应用中心-高级信息”设置回调页面(设置后一般…

flex java oracle_Flex使用Blazeds与Java交互及自定义对象转换详解-DATAGRID读取ORACLE数据...

一、建立Flex与Java交互的工程。本文中讲到的交互是利用Blazeds的,因为这个是免费的,呵呵,我是穷人。首先就是去下载Blazeds的压缩包,这个可以从官网或者CSDN、JavaEye上下到。解压缩这个包,将里面的Blazeds.war解压&a…

lfu算法实现java_LFU五种实现方式,从简单到复杂

前言最近刷力扣题,对于我这种 0 基础来说,真的是脑壳疼啊。这个月我估计都是中等和困难题,没有简单题了。幸好,力扣上有各种大牛给写题解。看着他们行云流水的代码,真的是羡慕不已。让我印象最深刻的就是人称 “甜姨”…

java控制台高级_K9s Kubernetes的高级控制台

K9s Kubernetes CLI,以个性化方式管理您的集群!参考:Why K9s?首先我们得面对现实——Kubernetes及其周边生态系统的运营方式正变得越来越复杂。集群管理需要大量工具加以配合。当我在集群之上进行日常运营时,和大家一样…

java缓存回收_java缓存应用 - 阿亮ing的个人空间 - OSCHINA - 中文开源技术交流社区...

缓存回收策略1.基于空间设置缓存的存储空间,超过容量限制按照一定的规则去移除。2.基于容量当缓存条数超过规定容量按照一定的规则去移除旧数据。3.基于时间(存活时间空闲时间)TTl(Time To Live):存活期,缓存数据最后更新时间到指定时间如果没有更新或创…

php 生成打印送货单,PHP输出PDF打印HTML5+CSS3打印格式控制

ERP系统进入尾声,各种送货单、退货单、合同、对账单等等一系列的东东排着队调打印格式。HTML5CSS3已经这样流行,然则眼下,基于CSS3的打印控制,居然还处于原始部落阶段,Chrome、Firefox、Edge等连简单的page都支持得不完…