MySQL的高阶学习:索引、B+树

news2025/1/12 2:46:21

1.索引

      索引是一种数据结构,如果没有索引,查找一个数据就需要从第一页开始全局检索直至找到需要的数据,有了索引可以先在目录中根据拼音查找到该数据所在的页数,因此通过索引可以大大减少了查询时间。

      索引有两种存储类型:B树(BTREE)索引和哈希(HASH)索引,InnoDB和MyISAM存储引擎支持BTREE索引,INNODB支持自适应HASH,MEMORY默认HASH索引。

1.1 B+索引

      1)因为二叉树每个节点只存储一条记录,数据量大会导致深度过深,查询会增加磁盘【MySQL数据存在磁盘,默认页根节点即第一页的数据存储在内存,每次读取数据都是从磁盘加载到内存的】IO次数;2)所以变种了B树:N叉节点【高度降低,查询速度变快】,且每个节点都可存储数据一页16KB(=磁盘块),通过中序遍历去查找;3)再升级为B+树,只叶子节点存数据,其余节点存关键字,层级更小,且叶子节点带有双向链表,可通过next快速访问,查询速度更快,更适合做存储引擎索引

其设计逻辑是这样的:1)内存读写快,磁盘读写慢,而且慢很多
2)磁盘预读:磁盘读写并不是按需读取,而是按页预读,一次会读一页的数据,每次加载一些看起来是冗余的数据,如果未来要读取的数据就在这一页中,可以避免未来的磁盘读写,提高效率(通常,一页数据是4KB),innodb是16KB
 3)局部性原理:软件设计要尽量遵循“数据读取集中”与“使用到一个数据,大概率会使用其附近的数据”,这样磁盘预读能充分提高磁盘IO效能。

B树特征:

  1. 根节点至少包含两个孩子
  2. 树中每个结点最多含有m个孩子(m >= 2)
  3. 除了根节点和叶结点外,其他每个结点至少含有ceil(m/2)个孩子,ceil为向上取整
  4. 所有叶子结点位于同一层(高度相同)

1.1.1二叉查找树

        节点中存储了键(key)和数据(data)。键对应 user 表中的 id,数据对应 user 表中的行数据,通常意味着所有的值按照顺序存储,二叉查找树的特点就是任何节点的左子节点的键值都小于当前节点的键值,右子节点的键值都大于当前节点的键值。顶端的节点我们称为根节点,没有子节点的节点我们称之为叶节点。利用二叉查找树我们只需要 3 次即可找到匹配的数据。如果在表中一条条的查找的话,我们需要 6 次才能找到。

1

1.1.2平衡二叉树(AVL)

        二叉树如果高度过高,会变得不平衡,查找也会变慢,所以需要平衡二叉树,在满足二叉查找树的前提下,要求每个节点左右子树的高度不超过1。平衡二叉树保证了树的构造是平衡的,当我们插入或删除数据导致不满足平衡二叉树不平衡时,平衡二叉树会进行调整树上的节点来保持平衡。

3

1.1.3 B-树

以下为3阶树,节点个数>=3,就会生成新的节点。

以下节点的形成说明,使用自增ID,然后追加数据的时候移动范围小,减少索引的维护成本!!!

 

 

      因为内存的易失性。一般情况下,我们都会选择将 user 表中的数据和索引存储在磁盘这种外围设备中,但和内存相比,从磁盘中读取数据的速度会慢上百倍千倍甚至万倍,所以应当尽量减少从磁盘中读取数据的次数。另外,从磁盘中读取数据时,都是按照磁盘块来读取的,并不是一条一条的读。如果我们能把尽量多的数据放进磁盘块中,那一次磁盘读取操作就会读取更多数据,那我们查找数据的时间也会大幅度降低。如果我们用树这种数据结构作为索引的数据结构,那每查找一次数据就需从磁盘中读取一个节点,也就是我们说的一个磁盘块

      我们都知道平衡二叉树是每个节点只存储一个键值和数据的,那如果我们要存储海量的数据呢?我们应该寻找一种单个节点可以存储多个键值和数据的平衡树。也就是我们接下来要说的 B 树。B 树(Balance Tree)即为平衡树的意思:

       p 节点为指向子节点的指针,二叉查找树和平衡二叉树其实也有,因为图的美观性,被省略了,每个节点称为页,页就是我们上面说的磁盘块,在 MySQL 中数据读取的基本单位都是页,所以我们这里叫做页更符合 MySQL 中索引的底层数据结构。B 树相对于平衡二叉树,每个节点存储了更多的键值(key)和数据(data),并且每个节点拥有更多的子节点,子节点的个数一般称为阶上述图中的 B 树为 3 阶 B 树,高度也会很低。

基于这个特性,B 树查找数据读取磁盘的次数将会很少,数据的查找效率也会比平衡二叉树高很多,假如我们要查找 id=28 的用户信息,那么我们在上图 B 树中查找的流程如下:

  • 先找到根节点也就是页 1,判断 28 在键值 17 和 35 之间,那么我们根据页 1 中的指针 p2 找到页 3。
  • 将 28 和页 3 中的键值相比较,28 在 26 和 30 之间,我们根据页 3 中的指针 p2 找到页 8。
  • 将 28 和页 8 中的键值相比较,发现有匹配的键值 28,键值 28 对应的用户信息为(28,bv)。

5

1.1.4  B+树

      B+ 树是对 B 树的进一步优化, B+ 树中各个页之间是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的。B树和B+树的区别:

      ①B+ 树非叶子节点上是不存储数据的,仅存储键值【如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的 IO 次数又会再次减少,数据查询的效率也会更快】,而 B 树节点中不仅存储键值,也会存储数据。

      ②因为 B+ 树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的。

 那么 B+ 树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。而 B 树因为数据分散在各个节点,要实现这一点是很不容易的。

6

1.2 Hash索引

      Memeory默认Hash索引。普通的哈希算法是取余,即对每个数&&00001111,大抵情况下来只是低位发生了变化;所以可以使其高位向低位移动,使数据散列更加均匀放置,hash的数据会放入内存,且大多数查询不只是=查询,不支持范围查询,所以不合适。

1.3 聚集索引、非聚集索引:数据和索引是否聚集存储的

①聚集索引(聚簇索引):是基于主键创建的索引,叶子节点中,索引关键字和数据是在一起存放的,在磁盘存储上,InnoDB聚集索引存在两个文件:student.frm(存储表的结构)||student.ibd(存放索引和数据)。聚集索引并不是仅仅是一种索引类型,还代表的一种数据存储方式。并且表必须有一个主键,如果没有主键InnoDB会默认选择一个隐藏列(rowid),作为主键索引来存储表的数据,一般情况是建议自增id作为主键。有连续性的在磁盘下入性能和检索性能上都会很高。如果使用uuid这种随机id的话,频繁插入会导致磁盘随机io,从而性能下降。并且一个表只能存在一个聚集索引,如果有多个就会有多套副本,浪费磁盘空间,并且当操作的时候会让数据维护更困难。

②非聚集索引(非聚簇索引):索引文件和数据文件是分离的MyISAM引擎索引结构的叶子节点的data域存放的并不是实际的数据记录,而是数据记录的地址。student.frm(存储表的结构)||student.MYD(存储表的数据)      ||student.MYI(存放表的索引数据)。非聚集索引子节点存放的不是实际数据,而是指向实际数据的指针,一个表中可以拥有多个非聚集索引

利用聚集索引查找数据:表中的数据存储在其中

8

 利用非聚集索引查找数据:

我们最终会找到主键值 47,找到主键后我们需要再到聚集索引中查找具体对应的数据信息,此时又回到了聚集索引的查找流程。

92

明白了聚集索引和非聚集索引的定义,我们应该明白这样一句话:数据即索引,索引即数据。

1.3.1 为什么不用红黑树?

答:红黑树多用于内部排序,即全放在内存中;B+树多用于外存上时,B+也被成为一个磁盘友好的数据结构;红黑树和平衡二叉树有相同缺点,每个节点存储一个关键词,数据量大时,导致红黑树的深度很深,mysql每次读取时消耗大量io。

1.3.2 为什么建议使用连续id?

答:有连续性的在磁盘写入性能检索性能上都会很高。如果使用uuid这种随机id的话,频繁插入会导致磁盘随机io,从而性能下降。

1.3.3 为什么一个表只有一个聚集索引?

答:如果有多个就会有多套副本,浪费磁盘空间,并且当操作的时候会让数据维护更困难。

1.3.4   mysql的索引一般有几层?

答:一般情况下,3到4层足以支撑千万级别的查询

1.3.5  创建索引的字段是长了好还是短了好?

答:短了好,因为短的花,一个页datapage可以存储更多的数据。

1.3.6  创建表的时候用代理主键还是自然主键?

 答:尽可能使用代理主键【 自然主键 事物属性中的自然唯一标识,常见的例子有:身份证号、手机号、学号等;代理主键(推荐使用) 与业务无关、无意义的数字序列值,例如数据库当中的表主键】

1.3.7  主键设置好之后,要不要自增?

答:在满足业务的情况下尽可能自增【B+树的移动范围最小】,不自增会增加索引的维护成本。

1.3.8  分布式场景下,自增id无效,该如何处理?

答:雪花算法,snowflake,自定义id生成器有很多,原理:使用一个 64 bit 的 long 型的数字作为全局唯一 ID。在分布式系统中的应用十分广泛,且 ID 引入了时间戳,基本上保持自增的;是 64 位 的二进制,1位是符号位,也就是最高位,始终是0,没有任何意义,因为要是唯一计算机二进制补码中就是负数,0才是正数。41位是时间戳,具体到毫秒,41位的二进制可以使用69年,因为时间理论上永恒递增,所以根据这个排序是可以的。

  • 依赖服务器时间,服务器时钟回拨时可能会生成重复 id。算法中可通过记录最后一个生成 id 时的时间戳来解决,每次生成 id 之前比较当前服务器时钟是否被回拨,避免生成重复 id。

1.3.9  mysql的回表?

创建联合索引就不会回表了!!!

ID直接查出结果

因为是根据主键的查询方式,则只需要搜索 ID 这棵 B+ 树,树上的叶子节点存储了行记录,根据这个唯一的索引,MySQL 就能确定搜索的记录

*  EXPLAIN SELECT * FROM t_back_to_table WHERE id = 3;

需要回表:

普通索引也叫二级索引,除聚簇索引外【存值】的索引都是普通索引,即非聚簇索引【存储了指针地址】

因为通过 drinker_id 这个普通索引查询方式,则需要先搜索 drinker_id 索引树(该索引树上记录着主键ID的值),然后得到主键 ID 的值为 3,再到 ID 索引树搜索一次。这个过程虽然用了索引,但实际上底层进行了两次索引查询,这个过程就称为回表。

*   SELECT * FROM t_back_to_table WHERE drinker_id = 3;

1.3.10 覆盖索引?

 1.3.11  最左索引?

答;最左前缀原则,顾名思义,就是最左边的优先。。指的是联合索引中【联合索引中的字段(name,age)都应该出现在索引树上的】,优先走最左边列的索引。如 index(a,b,c) 联合索引,则相当于创建了 a 单列索引,(a,b)联合索引,和(a,b,c)联合索引

参考:最左索引问题?_冬子一定要努力的博客-CSDN博客_最左索引

 1.3.13 索引下推?

答:索引下推在非主键索引上的优化,可以有效减少回表的次数,大大提升了查询的效率,可设置参数关闭:set optimizer_switch='index_condition_pushdown=off';

 5.6之后:

1.3.14   explain个参数详解:

 

idSELECT识别符。这是SELECT的查询序列号
select_type

SELECT类型,可以为以下任何一种:

  • SIMPLE:简单SELECT(不使用UNION或子查询)
  • PRIMARY:主查询,即最外面的查询
  • UNION:UNION中的第二个或后面的查询语句
  • DEPENDENT UNION:UNION中的第二个或后面的SELECT语句,取决于外面的查询
  • UNION RESULT:UNION 的结果
  • SUBQUERY:子查询中的第一个SELECT
  • DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询
  • DERIVED:导出表的SELECT(FROM子句的子查询)
table

输出的行所引用的表

type

联接类型。下面给出各种联接类型,按照从最佳类型到最坏类型(由上到下性能逐渐变差)进行排序:

  • system:表仅有一行(=系统表)。这是const联接类型的一个特例。
  • const:表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!
  • eq_ref:类似ref,区别就在使用的索引是唯一索引,对于每个来自于前面的表的行组合,从该表中读取一行,多表连接中使用unique index或者primary key作为关联条件。这可能是最好的联接类型,除了const类型。
  • ref:对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取(使用非唯一索引扫描或唯一索引的前缀扫描,返回匹配某个单独值的记录行)。
  • ref_or_null:该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。
  • index_merge:该联接类型表示使用了索引合并优化方法。
  • unique_subquery:该类型替换了下面形式的IN子查询的ref: value IN (SELECT primary_key FROM single_table WHERE some_expr) unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。
  • index_subquery:该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引: value IN (SELECT key_column FROM single_table WHERE some_expr)
  • range:只检索给定范围的行,使用一个索引来选择行,常见于<,<=,>,>=,between等操作符。
  • index:该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。
  • ALL:对于每个来自于先前的表的行组合,进行完整的表扫描,全表扫描。
possible_keys

指出MySQL能使用哪个索引在该表中找到行,表示查询时可能使用的索引。

key显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL。
key_len显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。
ref显示使用哪个列或常数与key一起从表中选择行。
rows显示MySQL认为它执行查询时必须检查的行数。多行之间的数据相乘可以估算要处理的行数。
filtered显示了通过条件过滤出的行数的百分比估计值。
Extra

该列包含MySQL解决查询的详细信息:

  • Distinct:MySQL发现第1个匹配行后,停止为当前的行组合搜索更多的行。
  • Not exists:MySQL能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,不再为前面的的行组合在该表内检查更多的行。
  • range checked for each record (index map: #):MySQL没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。
  • Using filesort:MySQL需要额外的一次传递,以找出如何按排序顺序检索行。
  • Using index:从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。
  • Using temporary:为了解决查询,MySQL需要创建一个临时表来容纳结果。
  • Using where:WHERE 子句用于限制哪一个行匹配下一个表或发送到客户。
  • Using sort_union(...), Using union(...), Using intersect(...):这些函数说明如何为index_merge联接类型合并索引扫描。
  • Using index for group-by:类似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,可以用来查 询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表。

参考:

MySQL索引-B+树(看完你就明白了)_拿钢叉的闰土的博客-CSDN博客

2.词法分析器

mysql里的全文索引不怎么用,类似于ES。

 

 

 

 

 

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

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

相关文章

金融科技赋能 互融云手机回租系统 实现资产全流程在线运营管理

在共享单车、充电宝等共享商业的兴起与成熟之后&#xff0c;“信用租赁”的模式悄然诞生&#xff0c;租房、租衣、租数码等已成常态。信用租赁系统的出现&#xff0c;带活了一大批租赁经济&#xff0c;尤其是手机行业。 伴随手机零售业的增长以及新品发布速度的提高&#xff0…

CY8C5888AXQ-LP096 CY8C5888AXI-LP096,IC MCU 32BIT

PSoC 5LP是一种真正的可编程嵌入式片上系统&#xff0c;集成了可配置的模拟和数字外设&#xff0c;内存和单芯片上的微控制器。PSoC 5LP架构通过以下方式提高性能&#xff1a; 32位Arm Cortex-M3核心加上DMA控制器和数字滤波处理器&#xff0c;最高可达80mhz 超低功率&#xff…

China SAFe Day 2022中国规模化敏捷大会圆满落幕!

China SAFe Day 202211月5日&#xff0c;2022 China SAFe Day暨第三届中国规模化敏捷大会在上海圆满落幕。 本届大会由Scrum中文网和SAI&#xff08;Scaled Agile Inc.&#xff09;联合主办&#xff0c;围绕 “敏捷企业与数字化变革” 这一主题展开&#xff0c;内容涵盖工业敏…

RSA加密原理与RSA公钥加密系统、数字签名

通过公钥加密系统&#xff0c;可以对传输于两个通信单位之间的消息进行加密&#xff0c;即使窃听者窃听到加密之后的消息&#xff0c;也不能对其破译。 1、RSA公钥加密原理 1.1 几个核心概念 公钥P与公钥函数P()密钥S与密钥函数S() 可以简单理解&#xff0c;一个公钥对应一个…

【数据结构】—— 单链表的增删改查

❤️一名热爱Java的大一学生&#xff0c;希望与各位大佬共同学习进步❤️ &#x1f9d1;个人主页&#xff1a;周小末天天开心 各位大佬的点赞&#x1f44d; 收藏⭐ 关注✅&#xff0c;是本人学习的最大动力 感谢&#xff01; &#x1f4d5;该篇文章收录专栏—数据结构 目录 方…

BUUCTF web之随便注

启动靶场访问如下&#xff0c;输入1&#xff0c;报错&#xff0c;可知是字符型注入&#xff0c;变量由单引号包裹 输入1 and 11 --&#xff0c;显示正常 先直接用sqlmap注入一下&#xff0c;显示存在注入&#xff0c;但是始终注入不出来数据库&#xff0c;“[ERROR] unable to …

Arnold渲染器适合什么样的电脑配置

Arnold 是 Solid Angle 和 Sony Pictures Imageworks 联合打造的顶级光线追踪 3D 渲染器。该程序是 Sony Imageworks 的主要渲染器&#xff0c;被全球 300 多家工作室使用。Arnold 6.0 及更高版本支持 GPU 渲染。Arnold GPU 的硬件建议是什么&#xff1f; 1. Arnold GPU 硬件推…

OpenKylin适配和虚拟打印机

最近在测国产OS客户端部分。首先客户端程序在CentOS全部使用没毛病&#xff0c;但是CentOS桌面体验比较差。然后就试了UOS&#xff0c;在UOS上测试到打印这块花了很多时间&#xff0c;碰到问题是CUPS有反应&#xff0c;但是没生成PDF文件&#xff0c;各种试了好久没解决。就寻思…

Android:单Activity多Fragment,Navigation实现Fragment跳转,Fragment之间通过ViewModel共享数据

单Activity多Fragment&#xff0c;Navigation实现Fragment跳转&#xff0c;Fragment之间通过ViewModel共享数据1、MainActivity2、HomeFragment, DetailFragment2.1、HomeFragment2.2、DetailFragment3、MyViewModel参考1、MainActivity 1、activity_main.xml <?xml vers…

ovs-vswitchd的启动分析

ovs-vswitchd的启动分析&#xff08;无修改源码&#xff09; &#xff08;一&#xff09;主要数据结构和概念了解 1.概念 在 OVS 中, 有几个非常重要的概念&#xff1a; Bridge: Bridge 代表一个以太网交换机&#xff08;Switch&#xff09;&#xff0c;一个主机中可以创建一…

Metabase学习教程:提问-4

Metabase中的表连接 如何在简单和自定义问题中使用查询编辑器连接Metabase中的表。 当涉及到分析数据时&#xff0c;必须要使用连接是一个事实&#xff0c;在Metabase&#xff0c;我们试图使您的问题的答案尽可能简单&#xff0c;即使这需要一些更复杂的策略。在本文中&#…

Spring中拦截器重复注册的问题排查

注册器JpushInterceptor 功能&#xff1a;新版的Java推送服务&#xff0c;将部分请求转发到老版node 查看日志发现拦截器日志重复 同一个链路&#xff0c;发现&#xff0c;经过同一个拦截器两次 debug发现注册器重复注册 第一个通过registry.addInterceptor注册 是通过We…

组合数学总结

文章目录三、递推关系3.1 常系数线性递推关系特征根法1.齐次递推关系2.非齐次方程母函数方法三、递推关系 3.1 常系数线性递推关系 k阶齐次递推关系&#xff1a;anc1an−1c2an−2...ckan−k0&#xff0c;ck≠0(3.1.1)k阶非齐次递推关系&#xff1a;anc1an−1c2an−2...ckan−kf…

SpringCloud微服务(四)——Nacos服务注册和配置中心

SpringCloud Alibaba Nacos服务注册和配置中心 Spring Cloud Netflix Projects Entering Mainterance Mode SpringCloud Alibaba&#xff1a; 服务限流降级&#xff1a;默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 Rocke…

在 UltraEdit v15.00 及更高版本中添加用于语法高亮的 wordfile丨使用教程

UltraEdit原生支持开箱即用的最常用编程和标记语言的语法突出显示。但是&#xff0c;我们也有数百个其他语言的单词文件&#xff0c;而且很容易找到并添加您需要的语言&#xff01;重要提示&#xff1a;此电源提示适用于运行 UltraEdit v15.00或 UEStudio v09.10及更高版本的用…

rosjava零散

笔者之前想在非ros环境下使用通信&#xff0c;了解到rosjava可以实现&#xff0c;不过后来换成了rosbridge&#xff0c;也搜集了一些rosjava的资料&#xff0c;放在这里供参考(没时间整理了&#xff0c;格式较乱请见谅) 安装方式&#xff1a;sudo apt-get install ros-indigo-…

Blind Backdoors in Deep Learning Models 论文笔记

#论文笔记# 1. 论文信息 论文名称Blind Backdoors in Deep Learning Models作者Eugene Bagdasaryan Vitaly Shmatikov Cornell Tech出版社USENIX Security Symposium 2021 &#xff08;网安A类会议&#xff09;pdf论文主页 本地PDF代码pytoch_Backdoors_101 2. introduction …

《第一行代码》核心知识点:Android简介

前言 自本文开始&#xff0c;我将更新《第一行代码 Android 第2版.pdf》&#xff0c;&#xff08;提取码&#xff1a;n5ag &#xff09; 核心要点系列&#xff0c;通过阅读本系列文章可以帮助有Android基础的开发人员&#xff0c;去除冗余的基础讲解&#xff0c;直击核心知识点…

GEE开发之Modis_ET数据分析和获取

GEE开发之Modis_ET数据获取1 ET(蒸散量)2 MOD16A2(500米/8天)2.1 MOD16A2下的所有指数2.2 ET影像获取和查看3 ET日数据下载(以MOD16A2为例)4 ET月数据下载(以MOD16A2为例)5 ET年数据下载(以MOD16A2为例)前言&#xff1a;主要介绍Modis下的ET数据的获取和下载&#xff08;日数据…

工厂模式【简单工厂+工厂+抽象工厂】总结

一、简单工厂模式 描述 简单工厂模式是属于创建型模式&#xff0c;又叫做静态工厂方法模式&#xff0c;但不属于23种GOF设计模式之一。简单工厂模式中专门定义一个简单工厂类来负责创建其他类的实例&#xff0c;被创建的实例通常都具有共同的父类。简单工厂类根据传入的参数&a…