从0开始回顾MySQL---系列三

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 索引1、没有索引如何查找数据?在一个页中的查找,分为两种情况: 以主键为搜索条件可以在 页目录 中使用二分法快速定位到对应的槽,然后再遍历该槽对应 分组中的记录即可快速找到指定的记录。以其他列作为搜索条件 对非主键列的查找的过程可就不这么幸运了,因为在数据页中并没有对非主键列建立所谓的 页目录 ,所以 我们无法通过二分法快速定位相应的 槽 。这种情况下只能从 最小记录 开始依次遍历单链表中的每条记录, 然后对比每条记录是不是符合搜索条件。很显然,这种查找的效率是非常低的。在很多页中的查找,可以分为两个步骤: 定位到记录所在的页。 从所在的页内中查找相应的记录。在没有索引的情

索引

1、没有索引如何查找数据?


在一个页中的查找,分为两种情况:

  1. 以主键为搜索条件

可以在 页目录 中使用二分法快速定位到对应的槽,然后再遍历该槽对应 分组中的记录即可快速找到指定的记录。

  1. 以其他列作为搜索条件

对非主键列的查找的过程可就不这么幸运了,因为在数据页中并没有对非主键列建立所谓的 页目录 ,所以 我们无法通过二分法快速定位相应的 。这种情况下只能从 最小记录 开始依次遍历单链表中的每条记录, 然后对比每条记录是不是符合搜索条件。很显然,这种查找的效率是非常低的。

在很多页中的查找,可以分为两个步骤

  1. 定位到记录所在的页。
  2. 从所在的页内中查找相应的记录。

在没有索引的情况下,不论是根据主键列或者其他列的值进行查找,由于我们并不能快速的定位到记录所在的页,所以只能从第一个页沿着双向链表一直往下找,在每一个页中根据我们刚刚唠叨过的查找方式去查找指定的记录。


2、索引是什么?


索引本质是排好序的数据结构,一种特殊的文件,包含着对数据表里所有记录的引用指针,直接在索引中查找符合条件的选项,加快数据库的查询速度,而不是一行一行去遍历数据后才选择出符合条件的。

优点

  • 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
  • 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

缺点

  • 索引是一个文件,它是要占据物理空间的。
  • 创建索引和维护索引要耗费时间,具体地,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,会降低增/改/删的执行效率。

3、MySQL有哪几种索引类型?


  1. 从数据结构上来划分:哈希索引,B树索引,B+树索引。
  2. 从功能层次上来划分:普通索引,唯一索引,主键索引,联合索引。
  • 普通索引:即一个索引只包含单个列,一个表可以有多个单列索引。
  • 唯一索引:索引列的值必须唯一,但允许有空值。
  • 主键索引:一种特殊的唯一索引,不允许有空值,一般在建表时同时创建主键索引;
  • 联合索引:多列值组成一个索引,专门用于组合搜索。
  1. 从物理存贮上来划分:聚簇索引,非聚簇索引。

4、聚簇索引和非聚簇索引?


聚簇索引聚簇索引是按照每张表的主键构造一颗B+树,叶子节点中存放的就是整张表的数据,将聚簇索引的叶子节点称为数据页。

c1,c2,c3三列,我们以c1列建立索引,索引树如下图所示:

聚簇索引的特点

聚簇索引不需要我们显式去创建,InnoDB 存储引擎会自动的为我们创建聚簇索引并且在 InnoDB 存储引擎中, 聚簇索引 就是数据的存储方式(所有的用户记录都存储在了叶子节点 ),也就是所谓的索引即数据,数据即索引

聚簇索引的优点

  • 数据访问更快,聚簇索引将索引和数据保存在同一个 B+ 树中,因此从聚簇索引中获取数据比非聚簇索引更快;
  • 聚簇索引对于主键的排序查找和范围查找速度非常快。

聚簇索引的缺点

  • 插入速度严重依赖于插入顺序,按照主键的顺序(递增)插入是最快的方式,否则将会出现页分裂,严重影响性能。
  • 更新主键的代价很高,将会导致被更新的行移动,所以对于 InnoDB 表,一般定义主键为不可更新。
  • 聚簇索引只能在搜索条件是主键值时才能发挥作用,因为 B+ 树中的数据都是按照主键进行排序的。


非聚簇索引非聚簇索引叶子节点存储的是主键值,而不是数据的物理地址,所以访问数据需要二次查找,推荐使用覆盖索引,可以减少回表查询。

以c2列作为索引列,建立B+树:

非聚簇索引的特点:

  • B+ 树的叶子节点存储的并不是完整的用户记录,而只是 索引列+主键 这两个列的值。
  • 以索引列大小排序的 B+ 树只能确定我们要查找记录的主键值,所以如果我们想根据 c2 列的值查找到完整的用户记录的话,仍然需要到 聚簇索引 中再查一遍,这个过程也被称为 回表

非聚簇索引的优点

  • 非聚簇索引由于不存储实际数据,所以实际文件较小,相比于聚簇索引再读取时可以减少磁盘IO。
  • 非聚簇索引使用主键作为”指针” 而不是使用地址值作为指针的好处是,减少了当出现行移动或者数据页分裂时辅助索引的维护工作。

非聚簇索引的缺点

  • 需要进行回表查询,即查询到对应的聚簇索引之后再通过聚簇索引查询到所需数据。

5、索引底层实现(数据结构)?


  1. Hash索引
  • 哈希表是一种以键—值(key-value)存储数据的结构,我们只要输入待查找的值即 key,就可以找到其对应的值即 Value。哈希的思路很简单,把值放在数组里,用一个哈希函数把 key 换算成一个确定的位置,然后把 value 放在数组的这个位置。
  • 不可避免地,多个 key 值经过哈希函数的换算,会出现同一个值的情况。处理这种情况的一种方法是,拉出一个链表。
  • 哈希表这种结构适用于只有等值查询的场景比如 Memcached 及其他一些 NoSQL 引擎。
  1. B 树索引
  • B 树索引,又称平衡树索引B Tree能加快数据的访问速度,因为存储引擎不再需要进行全表扫描来获取数据,数据分布在各个节点之中
  • 一棵 m 阶 B Tree 的特性如下:
  • 每个结点最多 m 个子结点;
  • 所有的叶子结点都位于同一层;
  • 每个节点中的元素按关键字key从小到大排列
  • 每个元素子左结点的值都小于或等于该元素,右结点的值都大于或等于该元素。
  • 数据库以 B-Tree 的数据结构存储数据的图示如下:

  1. B+Tree索引
  • 是B-Tree的改进版本,同时也是数据库索引所采用的存储结构。数据都在叶子节点上,并且增加了顺序访问指针,每个叶子节点都指向相邻的叶子节点的地址。相比B-Tree来说,进行范围查找时只需要查找两个节点,进行遍历即可。而B-Tree需要获取所有节点,相比之下B+Tree效率更高。
  • B+tree性质:
  • n棵子树的节点包含n个关键字,不用来保存数据而是保存数据的索引。
  • 所有的非叶子结点只存储 关键字key信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接;
  • 所有具体数据都存在叶子结点中;
  • 所有的叶子结点中包含了全部元素的信息;
  • 所有叶子节点之间都有一个链指针。
  • 数据库以 B+ Tree 的数据结构存储数据的图示如下:

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


B+树与B树相比:

  • B+树的磁盘读写代价更低:B+树的非叶子节点不存贮数据,只存贮关键词key信息,进行数据索引,使每个非叶子节点所能保存的关键字大大增加。这样磁盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了
  • 更加适合区间查询:B树的数据分布在各个节点之中,当进行范围查找时会出现回旋查找。而B+树的数据都存储在叶子结点中,并且MySQL 索引数据结构对经典的 B+Tree 进行了优化,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的 B+Tree,提高了区间访问的性能,防止回旋查找

B+树与Hash相比:

  • Hash虽然可以快速定位,但是没有顺序,IO复杂度高。
  • Hash索引基于Hash表实现,只有Memory存储引擎显式支持哈希索引 。
  • Hash索引因为不是按照索引值顺序存储的,就不能像B+Tree索引一样利用索引完成排序。
  • 如果有大量重复键值得情况下,哈希索引的效率会很低,因为存在哈希碰撞问题 。

B+树与红黑树相比:

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

B+树与普通二叉树相比:

  • 树的高度不均匀,不能自平衡,查找效率跟数据有关(树的高度),并且IO代价高。
  • 普通二叉树存在退化的情况,如果它退化成链表,相当于全表扫描。

B+树与平衡二叉树相比:

  • 读取数据的时候,是从磁盘读到内存。如果树这种数据结构作为索引,那每查找⼀次数据就需要从磁盘中读取⼀个节点,也就是⼀个磁盘块,但是平衡二叉树的每个节点只存储⼀个键值和数据,的节点将会非常多,高度也会极其高。如果是 B+ 树,可以存储更多的节点数据,树的高度也会降低,因此读取磁盘的次数就降下来了,查询效率就会更快。

7、索引的B+树到底有多高?


InnoDB中页的大小一般为16 KB,我们假设一行记录的数据大小为1KB(实际上现在很多互联网业务数据记录大小通常就是1K左右)

  • 如果 B+ 树只有1层,也就是只有1个用于存放用户记录的节点,可以存放 16KB / 1KB = 16条数据记录
  • 如果 B+ 树有2层:
  • 我们假设主键ID为bigint类型,长度为8字节,而指针大小在InnoDB源码中设置为6字节,这样一共14字节,一个页中共可以存放 16 * 1024 / 14 = 1170个指针,因此可以存放 1170 * 16 = 18720条数据记录
  • 如果 B+ 树有3层:可以存放 1170 * 1170 * 16 =  21902400,大约2000w条数据记录

所以在InnoDB中B+树高度一般为1-3层,它就能满足千万级的数据存储。在查找数据时一次页的查找代表一次IO,所以通过主键索引查询通常只需要1-3次IO操作即可查找到数据。

与此同时,我们也可以发现索引的B+树高度也跟索引字段的数据类型有关数据类型越小,索引占用的存储空间就越少,在一个数据页内就可以放下更多的记录,从而减少磁盘 I/O 带来的性能损耗,也就意味着可以把更多的数据页缓存在内存中,从而加快读写效率。


8、索引的代价(索引是不是越多越好)?


  1. 空间上的代价
  • 每建立一个索引都要为它建立一棵 B+ 树,每一棵 B+ 树的每一个节点都是一个数据页, 一个页默认会占用 16KB 的存储空间,一棵很大的 B+ 树由许多数据页组成,就是很大的一片存储空间,在增删改记录的时候性能就越差。
  1. 时间上的代价
  • 每次对表中的数据进行增、删、改操作时,都需要去修改各个 B+ 树索引。而增、删、改操作可能会对节点和记录的排序造成破坏,所以存储引擎需要额外的时间进行一些记录移位,页面分裂、页面回收啥的操作来维护好节点和记录的排序。
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6月前
|
存储 SQL 关系型数据库
从0开始回顾MySQL---系列八
分库分表 1、为什么要分库分表? 1. 数据库中的数据量不一定是可控的,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地数据操作,例如 增删改查的开销 也会越来越大;另外,若不进行分布式部署,而一台服务器的 资源 (CPU、磁盘、内存、IO 等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。 2. 所以,从 性能 和 可用性 角度考虑,会进行数据库拆分处理,具体地说,把原本存储于一个库的数据分块存储到多个库上,把原本存储于一个表的数据分块存储到多个表上,即 分库分表。 2、分库分表的具体实施策略 分库分表有 垂直切分 和 水平切分 两种方式,在
|
6月前
|
SQL 存储 关系型数据库
Mysql的NULLIF
Mysql的NULLIF
61 1
|
6月前
|
存储 关系型数据库 MySQL
从0开始回顾MySQL---系列一
基础 1、数据库的三范式是什么? 数据库范式是设计数据库时,需要遵循的一些规范。各种范式是条件递增的联系,越高的范式数据库冗余越小。常用的数据库三大范式为: 1. 第一范式(1NF):每个列都不可以再拆分,强调的是列的原子性,即数据库表的每一列都是不可分割的原 子数据项。 2. 第二范式(2NF):在满足第一范式的基础上,非主属性完全依赖于主码(主关键字、主键),消除非主属性对主码的部分函数依赖。 3. 第三范式(3NF):在满足第二范式的基础上,表中的任何属性不依赖于其它非主属性,消除传递依赖。简而言之,非主键都直接依赖于主键,而不是通过其它的键来间接依赖于主键。 2、MySQL 支持哪
|
6月前
|
存储 SQL 关系型数据库
从0开始回顾MySQL---系列四
9、什么是回表(使用索引查询完整数据过程)? 当我们需要查询一条完整的数据的时候: ● 如果是通过聚簇索引来查询数据,例如 select * from user where id=100,那么此时只需要搜索聚簇索引的 B+Tree 就可以找到数据。 ● 如果是通过非聚簇索引来查询数据,例如 select * from user where username=zhangsan',那么此时需要先搜索 username 这一列索引的 B+树,搜索完成后得到主键的值,然后再去搜索聚簇索引的 B+树,就可以获取到一行完整的数据。 对于第二种查询方式而言,一共搜索了两棵 B+树,第一次搜索 B+树 拿到
|
6月前
|
SQL 关系型数据库 MySQL
从0开始回顾MySQL---系列九
SQL优化 1、一条sql语句执行很慢的原因有哪些? ⚡ 一个SQL执行的很慢,我们要分两种情况讨论: 1. 大多数情况下很正常,偶尔很慢,则有如下原因: ● 数据库在刷新脏页(内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页),例如redo log 写满了需要同步到磁盘。 ● 执行的时候,遇到锁,如表锁、行锁。 ● sql语句写的不好。 2. 这条SQL语句一直执行的很慢,则有如下原因: ● 没有用上索引或者索引失效:比如该字段没有索引,由于对字段进行运算、函数操作导致无法用索引。 ● 有索引可能会走全表扫描: ○ 怎样判断是否走全表扫描? ○ 某
|
6月前
|
存储 缓存 关系型数据库
从0开始回顾MySQL---系列二
InnoDB记录结构 1、InnoDB行格式 ? ● 我们平时是以记录为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为 行格式 或者 记录格式 。 ● 设计InnoDB 存储引擎的作者到现在为止设计了4种不同类型的 行格式 ,分别是 Compact 、Redundant 、Dynamic 和 Compressed 行格式。 2、COMPACT行格式 ? 一条完整的记录其实可以被分为 记录的额外信息 和 记录的真实数据 两大部分。 记录的额外信息 这部分信息是服务器为了描述这条记录而不得不额外添加的一些信息,这些额外信息分为3类,分别是 变长字段长度列表 、 NULL值列表 和
|
6月前
|
存储 SQL 关系型数据库
从0开始回顾MySQL---系列五
事务 1、什么是数据库事务? 事务(Transaction)是访问和更新数据库的程序执行单元,是逻辑上的一组操作,要么都执行,要么都不执行。如果任意一个操作失败,那么整组操作即为失败,会回到操作前状态或者是上一个节点。 因此,事务是保持 逻辑数据一致性 和 可恢复性 的重要利器。而锁是实现事务的关键,可以保证事务的完整性和并发性。 事务控制语句: ● BEGIN 或 START TRANSACTION 显式地开启一个事务; ● COMMIT 也可以使用 COMMIT WORK,不过二者是等价的。COMMIT 会提交事务,并使已对数据库进行的所有修改成为永久性的; ● ROLLBAC
|
6月前
|
存储 关系型数据库 MySQL
从0开始回顾MySQL---系列七
锁 1、为什么要加锁? 1. 当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况,若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。 2. 因此加锁是为了在多用户环境下保证数据库完整性和一致性。 2、MySQL都有哪些锁呢? 锁的分类: ● 按操作分类: ○ 共享锁:也叫读锁。对同一份数据,多个事务读操作可以同时加锁而不互相影响 ,但不能修改数据 ○ 排他锁:也叫写锁。当前的操作没有完成前,会阻断其他操作的读取和写入 ● 按粒度分类: ○ 表级锁:会锁定整个表,开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并
|
6月前
|
存储 关系型数据库 MySQL
从0开始回顾MySQL---系列六
11、什么是MVCC? MVCC 全称 Multi-Version Concurrency Control,即多版本并发控制,用来解决读写冲突的无锁并发控制,可以在发生读写请求冲突时不用加锁解决,这个读是指的快照读(也叫一致性读或一致性无锁读),而不是当前读: ● 快照读:实现基于 MVCC,因为是多版本并发,所以快照读读到的数据不一定是当前最新的数据,有可能是历史版本的数据; ● 当前读:读取数据库记录是当前最新的版本(产生幻读、不可重复读),可以对读取的数据进行加锁,防止其他事务修改数据,是悲观锁的一种操作,读写操作加共享锁或者排他锁和串行化事务的隔离级别都是当前读。 -- 简单的sel
|
存储 SQL JSON
MySQL学习---17、MySQL8其它新特性
MySQL学习---17、MySQL8其它新特性
下一篇
无影云桌面