什么是索引

索引是帮助MySQL高效获取数据的排好序的数据结构

数据结构有哪些

数据结构模拟网站:Data Structure Visualization

  • 二叉树

不适合做自增ID的数据结构。如下示意图,假设采用二叉树作为表自增主键ID的数据存储结果如下:当查询id为5的数据时,其查询次数为5次

  • 红黑树

不适合做mysql的索引,因为当表数据太大时,树的高度也同时增大,导致高度不可控和查询速度同时变慢。

  • Hash表
  1. 对索引的key进行一次hash计算就可以定位出数据存储的位置
  2. 很多时候Hash索引要比B+ 树索引更高效
  3. 仅能满足 “=”,“IN”,不支持范围查询
  4. hash冲突问题

  • B-tree

每个节点都会保存data数据。

  • B+tree

Mysql存储结构和索引结构

1、存储结构

InnoDB存储引擎的逻辑存储结构和 Oracle大致相同 ,所有数据都被逻辑地存放在一个空间中 ,我们称之为表空间 ( tablespace ) 。表空间又由段 ( segment ) 、区 ( extent ) 、页 ( page ) 组成,InnoDB存储引擎的逻辑存储结构大致如图所示。

段(segment)

段是表空间文件中的主要组织结构,它是一个逻辑概念,用来管理物理文件,是构成索引、表、回滚段的基本元素。上图中显示了表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。InnoDB存储引擎表是索引组织的(index organized),因此数据即索引,索引即数据。那么数据段即为B+树的叶子节点(上图的leaf node segment),索引段即为B+树的非叶子节点(上图的non-leaf node segment)。

创建一个索引(B+树)时会同时创建两个段,分别是非叶子节点段和叶子节点段.。在索引数据量一直增长的过程中,所有新的存储空间的申请,都是从“段”这个概念中申请的。

区(extents)

innodb里的段(segment)又由多个区组成,在代码中被称为extent,区是由64个连续的页(page)组成的,每个页大小为16KB,即每个区的大小为1MB。一个区是物理上连续分配的一个段空间,每一个段至少会有一个区,在创建一个段时会创建一个默认的区。如果存储数据时,一个区已经不足以放下更多的数据,此时需要从这个段中分配一个新的区来存放新的数据。一个段所管理的空间大小是无限的,可以一直扩展下去,但是扩展的最小单位就是区。

页(page)

InnoDB有页(page)的概念,可以理解为区的细化,页是InnoDB磁盘管理的最小单位。

常见的页类型有:

  1. 数据页(B-tree Node)。
  2. Undo页(Undo Log Page)。
  3. 系统页(System Page)。
  4. 事务数据页(Transaction system Page)。
  5. 插入缓冲位图页(Insert Buffer Bitmap)。
  6. 插入缓冲空闲列表页(Insert Buffer Free List)。
  7. 未压缩的二进制大对象页(Uncompressed BLOB Page)。
  8. 压缩的二进制大对象页(Compressed BLOB Page)。

在逻辑上(页面号都是从小到大连续的)及物理上都是连续的。在向表中插入数据时,如果一个页面已经被写完,系统会从当前区中分配一个新的空闲页面处理使用,如果当前区中的64个页都被分配完,系统会从当前页面所在段中分配一个新的区,然后再从这个区中分配一个新的页面来使用;

索引结构B+树

B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构。B-Tree结构中每个节点不仅包含数据的key值,还有data值。而每一个页的存储空间是有限的,如果data数据较大时将会导致每个节点(即一个页)能存储的key的数量很小,当存储的数据量很大时同样会导致B-Tree的深度较大,增大查询时的磁盘I/O次数,进而影响查询效率。在B+Tree中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大增加每个节点存储的key值数量,降低B+Tree的高度。

B+Tree相对于B-Tree有几点不同:

(1)非叶子节点只存储关键字信息

(2)所有叶子节点之间都有一个双向链表指针

(3)数据记录都存放在叶子节点中

为什么使用B+Tree?

MySQL是基于磁盘的数据库系统,索引往往以索引文件的形式存储的磁盘上,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级(每次存取都是按页来操作的),所以要尽量减少索引树的高度。

(1)B+树的一个节点刚好也是一页。

(2)B+树索引节点不存储数据,因此一个索引节点可以存储更多的索引节点,每个节点能索引的范围更大更精确,也意味着 B+树单次磁盘IO的信息量大于其它树状结构,I/O效率更高。

(3)B+树的数据全部存储在叶子节点,而叶子节点是双向链表,可以很高效的实现区间查询。

库表文件存储位置

Mysql存储引擎

存储引擎是作用到表上的,不同存储引擎的存储内容不一样,同样的是都采用B+tree的索引结构(Mysql做了优化在叶子节点采用了双链表)。如下图示意中InnoDB与MyISAM存储引擎表对应的存储文件区别。

InnoDB:

•InnoDB索引文件和数据文件是一体的(聚集)

frm:存储表结构信息

ibd:存储索引和数据

主键索引

1、表数据文件本身就是按B+Tree组织的一个索引结构文件
2、聚集索引-叶节点包含了完整的数据记录

  • 为什么建议InnoDB表必须建主键,并且推荐使用整型的自增主键? 

建主键的目的是让存储引擎可以采用主键创建索引。如果没指定主键则系统会找表里边数据都不相同的列创建索引,如果表里边没有数据都不相同的列则创建一个隐藏列并维护1个rowid。

建议采用整形作为主键,是因为整形好做比较和排序且占用空间小。有的表可能采用UUID作为主键,UUID 虽然可以用字符的ASCII码进行比较,但是比较耗时间(比如比较两个UUID需要一位一位的比较)且长度比较大。

自增有利于顺畅的插入元素。如果不是自增的,则在插入新元素时可能发生树平衡和重构。

非主键索引
  • 为什么非主键索引结构叶子节点存储的是主键值?

(一致性和节省存储空间)

联合索引

联合索引需要遵循最左匹配原则。如果没有按照最左匹配则会导致查询不走索引。原理就如上图,假如查询条件没有name只有age和position字段查询条件,则会导致无法按照索引的排序去查找数据只能查全表。

从 MySQL 5.1 版本开始,MySQL 就开始支持将 B+ 树索引的所有非叶子节点放在内存中的优化方式,这被称为 InnoDB 的“主内存散列索引”(main memory hash index)或者简称为“散列索引”(hash index)。在这种优化方式下,非叶子节点不再使用 B+ 树结构存储,而是使用更高效的散列结构进行组织。

这种索引优化方式最早是在 InnoDB 存储引擎中引入的,然后逐渐得到了优化和改进。从MySQL 5.5版本开始,InnoDB 引入了更强大的“InnoDB Buffer Pool”(即内存缓冲池),并且支持将索引的数据和非叶子节点全部放入内存中,从而极大地提高了查询性能。

需要注意的是,虽然主内存散列索引可以显著提高查询性能,但它也需要消耗更多的内存资源。因此,在使用这种优化方式时,需要确保服务器具备足够的内存容量以容纳索引数据和非叶子节点。

MyISAM:

•MyISAM索引文件和数据文件是分离的(非聚集)

frm:存储表结构信息

MYD:存储表数据信息

MYI:存储表索引信息

相关文章

CentOS本地部署SQL Server数据库无公网ip环境实现远程访问

GeoServer是OGC Web服务器规范的J2EE实现,利用GeoServer可以方便地发布地图数据,允许用户对要素数据进行更新、删除、插入操作,通过GeoServer可以比较容易地在用户之间迅速共享空间地理信息。另外,GeoServer是开源软件。下面介绍GeoServer web ui 管理界面 结合cpolar 内网穿透工具实现远程访问,

[redis] redis的安装,配置与简单操作

Redis是一个开源、基于内存、使用C语言编写的key-value数据库,并提供了多种语言的API。它的数据结构十分丰富,主要可以用于数据库、缓存、分布式锁、消息队列等...Redis服务器程序是单进程模型,也就是在一台服务器上可以同时启动多个Redis进程,Redis的实际处理速度则是完全依靠于主进程的执行效率。若在服务器上只运行一个Redis进程,当多个客户端同时访问时,服务器的处理能力是会有一定程度的下降;

Redis的IO多路复用原理解析

模拟一个tcp服务器处理30个客户socket,一个监考老师监考多个学生,谁举手就应答谁。假设你是一个监考老师,让30个学生解答一道竞赛考题,然后负责验收学生答卷,你有下面几个选择:第一种选择:按顺序逐个验收,先验收A,然后是B,之后是C、D。。。这中间如果有一个学生卡住,全班都会被耽误,你用循环挨个处理socket,根本不具有并发能力。第二种选择:你创建30个分身线程,每个分身线程检查一个学生的答案是否正确。这种类似于为每一个用户创建一个进程或者线程处理连接。

在 Docker 中配置 MySQL 数据库并初始化 Project 项目

这样,您就完成了在 Docker 中配置 MySQL 数据库并初始化 Project 项目的过程。希望这篇博客对您有所帮助!创建目录 /project/mysql 以及 /project/mysql_data。在每个 SQL 文件中,将 AUTO_INCREMENT 修改为 1。将准备好的 SQL 文件复制到 /project/mysql 目录。将 init.sql 放到 /project/mysql 目录。在 SQL 文件中插入管理员相关数据。在 SQL 文件中插入机型相关数据。1.4. 插入管理员。

深入理解Mysql事务隔离级别与锁机制

我们的数据库一般都会并发执行多个事务,多个事务可能会并发的对相同的一批数据进行增删改查操作,可能就会导致我们说的脏写、脏读、不可重复读、幻读这些问题。这些问题的本质都是数据库的多事务并发问题,为了解决多事务并发问题,数据库设计了事务隔离机制、锁机制、MVCC多版本并发控制隔离机制,用一整套机制来解决多事务并发问题。接下来,我们会深入讲解这些机制,让大家彻底理解数据库内部的执行原理。

Redis数据一致解决方案

在高并发的业务场景下redis与mysql数据库非常容易产生数据不一致的情况,我们可以采用redis缓存延迟双删除策略达到数据的最终一致性,也可以采用一部缓存更新自定义监听mysql binblog和采用canal开源中间件实现缓存的实时一致性方案。总的来说,都是比较简单的,而且都能够达到良好的效果。

如何在Linux设置JumpServer实现无公网ip远程访问管理界面

JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。JumpServer 帮助企业以更安全的方式管控和登录所有类型的资产,实现事前授权、事中监察、事后审计,满足等保合规要求。下面介绍如何简单设置即可使本地jump server 结合cpolar 内网穿透实现远程访问jump server 管理界面.

复杂 SQL 实现分组分情况分页查询

在处理数据库查询时,分页是一个常见的需求。尤其是在处理大量数据时,一次性返回所有结果可能会导致性能问题。因此,我们需要使用分页查询来限制返回的结果数量。同时,根据特定的条件筛选数据也是非常常见的需求。在本博客中,我们将探讨如何根据 camp_status 字段分为 6 种情况进行分页查询,并根据 camp_type 字段区分活动类型,返回不同的字段。我们将使用 SQL 变量来实现这一功能,并通过示例进行详细解释。

MyBatis入门配置及CRUD实现

MyBatis的主要作用是简化Java应用程序与关系型数据库之间的交互。通过使用MyBatis,开发人员可以通过简单的配置和编写SQL语句,实现对数据库的增删改查操作。同时,MyBatis还提供了一些高级特性,如分页查询、批量操作等,使得数据库访问更加灵活和高效。总之,MyBatis是一个功能强大、易于使用的持久层框架,被广泛应用于Java开发中。

【MyBatis】自定义resultMap三种映射关系

一对一关系使用associationid:id:表示自定义映射的唯一标识 type:查询的数据要映射的实体类的类型 result:设置普通字段的映射关系association设置多对一的映射关系collection property:设置映射关系中实体类中的属性名column:设置映射关系中表中的字段名最后,编写一个查询方法来使用这个 resultMap:

【具有路由 WSN 模拟器的随机方式移动】具有路由 WSN 模拟器的随机方式移动(Matlab代码实现)

这种随机的节点移动模拟了真实世界中节点的行为,因为无线传感器网络中的节点通常不会按照固定的轨迹移动。最后,我们评估了我们提出的方法的效果和性能。我们通过比较在使用我们的方法时的数据传输延迟、能耗和网络吞吐量等指标与使用其他方法时的指标,来评估我们的方法的优劣。通过这些工作步骤,我们能够更好地理解路由 WSN 模拟器的随机方式移动,并评估其在无线传感器网络中的应用效果和性能。我们的研究对于改进无线传感器网络的路由策略和性能优化具有重要意义,并可以为实际网络部署提供有价值的参考。行百里者,半于九十。
返回
顶部