mysql的数据结构及索引使用情形

news2024/12/23 18:57:05

先来说下数据的一般存储方式:内存(适合小数据量)、磁盘(大数据量)。
磁盘的运转方式:速度 + 旋转,磁盘页的概念:每一页大概16KB。

1、存储结构

哈希

是通过hash函数计算出一个hash值的,哈希的优点就是查找的时间复杂度是O(1),哈希不支持部分索引查询以及范围查找。

红黑树

存储的数据量大的时候,红黑树的节点层数多,也就是树的高度比较高,查找的底层数据时,查找次数就比较多,即对磁盘IO使用比较频繁。总结为以下两点:

  1. 读取浪费太多:通过计算本来树的每一层大概需要分配16KB的数据,但是对于红黑树来说,实际存的节点数比较少,即存的数据大小远远小于16KB,从而造成存储空间的浪费
  2. 读取磁盘的次数过多:树的层数越多,查找数据时读取磁盘的次数也就越多

如下图所示,如果需要查找数字4的话,需要查找三次,即对磁盘IO操作三次:

image.png

针对红黑树以上总结的两点,我们可以从以下两点出发:

  1. 增加树每层的节点数量,这样可以对分配的16KB充分利用,即解决上面的读取浪费的问题
  2. 尽可能的让树的高度减小,使得树显得比较“矮胖”,这样可以减少读取磁盘的次数

那么怎么样才可以实现以上的方法呢?这就需要用到B+树了,实际上MySql的底层数据结构就是用的B+树。

BTree

BTree的问题有以下这几点:

  1. 因为BTree不适合范围查找。就拿上面的来举例,比如我要查找小于6的数据,则先找到6的节点,然后需要遍历一遍6节点(索引)的左子树,不遍历的话,就拿不到小于6的这些数据了,也就说索引失效了,所以说不适合范围查找。
  2. BTree的节点除了存储索引之外,还存储了数据本身,占用空间较大,但是磁盘的页大小是有限的(16KB左右),因此,存储同样大小的数据,BTree显得比较高(相对B+Tree),稳定性弱一些。

综上两个主要原因,MySql最终选择了B+Tree的数据结构来存储数据。

B+Tree

B+Tree和BTree的分裂过程类似,只是B+Tree的非叶子节点不会存储数据,只存储索引值(指针地址),所有的数据都是存储在叶子节点,如下图所示:

btree-6.png

由上图可以看出B+Tree有以下几个特点:

  1. 叶子节点连起来了,是一条有序的双向链表,目的是为了解决范围查找。比如需要查找小于9的数据,只要找到等于9的数据,然后将9的左边数据全部拿出来即可。
  2. 非叶子节点不存数据,只存索引,空间利用更高效。
  3. 数据的个数和节点一样多,换句话说,非叶子节点存的是其子树的最大或最小值。

2、索引

2.1、索引功能类型

主键索引:一张表只能有一个主键索引,不允许重复、不允许为 NULL;
唯一索引:数据列不允许重复,允许为 NULL 值,一张表可有多个唯一索引,索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
普通索引:一张表可以创建多个普通索引,一个普通索引可以包含多个字段,允许数据重复,允许 NULL 值插入;
全文索引:它查找的是文本中的关键词,主要用于全文检索。

2.2、索引物理类型

聚簇索引(clustered index):聚簇索引也可理解为将数据存储与索引放到了一块,找到索引也就找到了数据。

非聚簇索引:数据和索引是分开的,B+树叶子节点存放的不是数据表的行记录。

虽然InnoDB和MyISAM存储引擎都默认使用B+树结构存储索引,但是只有InnoDB的主键索引才是聚簇索引,InnoDB中的辅助索引以及MyISAM使用的都是非聚簇索引。每张表最多只能拥有一个聚簇索引。

2.3、索引使用的不同情形

回表

若有student表如下

id(主键)    name    age
1               路飞      18
2               索隆      20
我们对id建立索引,然后再对name建立索引。那么当我们执行select * from  student where name=?时

由于索引底层数据结构的B+Tree,对name列建立的索引为非聚簇索引,这个索引存储的是id

那么我们执行完SQL时,会从name的B+Tree中拿到id,再回到id的B+Tree中去搜索所对应的数据,这个过程就叫做回表

索引覆盖

还是,假设有一条语句

select id from  student where name=?

此时,就不会再去再去id的对应索引的那颗B+Tree上再去搜索一遍了,这就是索引覆盖

最左匹配原则

一帮情况下和组合索引一起使用,例如吧name,age共同建立索引(name,age),假设现在有下面四条sql语句

select * from  student where name=? and age=?

select * from  student where name=?

select * from  student where age=?

select * from  student where age=? and name=?

现在问题来了,那个会走组合索引(name,age)?

答案是1,2,4,而3会进行全表扫描,看下图

听名知意,就是最左边开始匹配呗,也就是先匹配name,再来age。虽然2只有name,但是也会走索引。

你可能的疑惑就是4为啥会走索引,其实mysql中有个叫做优化器的东西,他会对这个age和name的顺序进行优化。这样就可以走索引了

优化器简单的说一下,有两种:CBO(基于成本的优化),RBO(基于规则的优化)MySQL默认用的是CBO。

索引下推

数据是存储在磁盘的、MySQL有自己的服务,MySQL服务要跟磁盘发生交互。这样能从磁盘拿到数据

没有索引下推时:

存储引擎先从磁盘中筛选出name符合条件的数据,全部取出,MySQL server再根据age条件筛选一次。这样就得到了符合条件的值。

这样会有大量的IO操作,所以浪费时间和资源

有存索引下推时:

存储引擎先从磁盘中直接筛选出name,age同时都符合条件的数据,不需要server再去做任何的数据筛选

索引下推需要在磁盘上进行数据筛选,原来的筛选是在内存中进行,现在放到了磁盘上进行查找数据的环节,但是,虽然这样看起来成本更高了,可别忘了,索引数据是排序的,所有数据是聚集存放的,所以性能并不会有影响,而且还会减少IO次数,反而会提升性能
                       

参考文献:

一文吃透MySql的底层数据结构(满满都是干货) - 掘金 (juejin.cn)

https://www.zhihu.com/question/26398102

https://blog.csdn.net/wangfeijiu/article/details/113409719

MySQL索引:回表、索引覆盖,最左匹配原则、索引下推_回表底层索引数据结构-CSDN博客

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

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

相关文章

重新规划路线

题目链接 重新规划路线 题目描述 注意点 题目数据 保证 每个城市在重新规划路线方向后都能到达城市 02 < n < 5 * 10^4connections.length n-1connections[i].length 20 < connections[i][0], connections[i][1] < n-1connections[i][0] ! connections[i][1] …

[leetcode]Z 字形变换

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:string convert(string s, int numRows) {int n s.length(), r numRows;if (r 1 || r > n) {return s;}int t r * 2 - 2;int c (n t - 1) / t * (r - 1);vector<string> mat(r, string(c, 0)…

Spring框架学习笔记(一):Spring基本介绍(包含容器底层结构)

1 官方资料 1.1 官网 https://spring.io/ 1.2 进入 Spring5 下拉 projects, 进入 Spring Framework 进入 Spring5 的 github 1.3 在maven项目中导入依赖 <dependencies><!--加入spring开发的基本包--><dependency><groupId>org.springframework<…

ISIS的工作原理

1.邻居关系建立 &#xff08;1&#xff09;IS-IS领接关系建立原则 1、通过将以太网接口模拟成点到点接口&#xff0c;可以建立点到点链路邻接关系。 2、当链路两端IS-IS接口的地址不在同一网段时&#xff0c;如果配置接口对接收的Hello报文不作IP地址检查&#xff0c;也可以建…

解决github的remote rejected|git存储库的推送保护

前言 git存储库的推送保护。当你试图推送代码到GitHub仓库时&#xff0c;由于存在与主分支&#xff08;master&#xff09;相关的仓库规则违规行为&#xff0c;推送会被拒绝了。这种保护机制帮助确保只有经过授权和符合规定的代码才能被合并到主分支&#xff0c;从而保护了主分…

【LeetCode刷题】410. 分割数组的最大值

1. 题目链接2. 题目描述3. 解题方法4. 代码 1. 题目链接 410. 分割数组的最大值 2. 题目描述 3. 解题方法 题目中提到的是某个和的最大值是最小的&#xff0c;这种题目是可以用二分来解决的。 确定区间&#xff0c;根据题目的数据范围&#xff0c;可以确定区间就是[0, 1e9]…

省份数量00

题目链接 省份数量 题目描述 注意点 1 < n < 200isConnected[i][j] 为 1 或 0isConnected[i][i] 1isConnected[i][j] isConnected[j][i] 解答思路 最初想到的是广度优先遍历&#xff0c;当某个城市不属于省份&#xff0c;需要从该城市开始&#xff0c;根据isConne…

直说了,你可能从没真正理解MPLS

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 你们好&#xff0c;我的网工朋友。 尽管 MPLS 技术已经相当成熟&#xff0c;有关它的文章数不胜枚举&#xff0c;涵盖了从基本原理到 SR-MPLS 等…

卸载系统自带APP

Firefly RK3588 android 12自动多个系统软件&#xff0c;无法从UI界面进行手动删除。因此&#xff0c;考虑使用shell指令进行处理。 系统自动APP大多都安装在system/app目录下&#xff0c;且该目录多为只读。因此采用如下步骤&#xff0c; //Shell su adb shell su //重新挂载…

【前端】HTML基础(2)

文章目录 前言一、HTML常见标签1、 注释标签1.1 标题标签1.2 段落标签1.3 换行标签 2、 格式化标签2.1 加粗标签2.2 倾斜标签2.3 删除线标签2.4 下划线标签 3、 图片标签3.1 src属性3.2 alt属性3.3 title属性3.4 图片大小3.5 图片边框 4、 超链接标签4.1 属性4.2 属性 前言 这篇…

从项目开始学习Vue——02(若依框架)

往期&#xff1a; 从项目开始学习Vue——01 目录标题 一、基础插件&#xff08;一&#xff09;路由Vue Router&#xff08;二&#xff09;导航守卫&#xff08;路由拦截器&#xff09;二、Vuex&#xff08;一&#xff09;什么是VuexVuex的部分介绍内容&#xff1a; &#xff08…

antdVue 自定义table列配置

最近做项目的时候需要对页面的table进行列配置的需求 子组件 <div><a-modaltitle"列配置" :visible"visible" :closable"false" :footer"null"width"800px" height"448px"><div><a-row>…

多C段的美国站群服务器有什么用途?

多C段的美国站群服务器有什么用途? 多C段的美国站群服务器是一种常见的网络运营策略&#xff0c;其用途主要体现在以下几个方面&#xff1a; 多C段的美国站群服务器有什么用途? 1. 提高站点排名和流量 部署多个站点在不同的C段IP地址上&#xff0c;可以通过不同的IP地址发布…

linux - 主次设备号自动申请

alloc_chrdev_region 原型如下&#xff0c;该函数向内核申请一个空闲的主设备号。 alloc_chrdev_region(&g_aputriger_dev, 0, APUTRIGER_MAX_NUM, "aputriger0"); 第四个参数是我们使用cat /proc/devices 看到的名称 /*** alloc_chrdev_region() - register a…

外包干了2年,人都要废了。。。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 简单的说下&#xff0c;我大学的一个同学&#xff0c;毕业后我自…

程序员技术文档编写神器Typora【图文详情】

文章目录 前言一、Typora是什么&#xff1f;二、如何安装三、如何使用总结 前言 在软件项目开发过程中&#xff0c;需要进行开发设计&#xff0c;编写相关的开发设计文档&#xff0c;本文介绍一下编写开发设计文档的神器Typora。 一、Typora是什么&#xff1f; Typora 是一款…

SinoDB数据库导入导出工具External table

External table又叫SinoDB外部表&#xff0c;外部表采用多线程机制&#xff0c;支持多线程读取、写入数据文件以及多线程数据转换、插入操作。多线程机制只需要消耗相对较少的系统资源&#xff0c;但是能提供高速数据导入、导出&#xff0c;可以应用在数据采集、表重建、数据库…

04-xss获取cookie实验

二、开发XSS服务器端 1、确认实验环境 攻击者服务器&#xff1a;192.168.74.134&#xff0c;将获取到cookie数据保存到该服务器的数据库中&#xff0c;运行PHP代码暴露一个接收Cookie的URL地址。 正常Web服务器&#xff1a;192.168.74.133&#xff0c;用于正常的用户访问的目…

java编程中,实现分页对象的类型转换

一、背景 当数据库分页查询返回的对象与接口要返回的对象类型不一致时&#xff0c;不可避免需要进行类型转换。 示例&#xff1a;数据库分页查询返回的对象是PageDTO&#xff0c;而接口返回的对象类型是PageVO。 PageDTO Data public class PageDTO<T> {/*** Current…

Android 巧用putBinder方法传递大文件

使用Intent传递数据大家都知道&#xff0c;但是如果你使用Intent传递大于1Mb的数据时&#xff0c;就一定会报如下的错误&#xff1a; Caused by: android.os.TransactionTooLargeException: data parcel size 1049112 bytes 就是说你的传输数据太大了&#xff0c;当前的大小达…