MySQL索引结构实例分析

简介

在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引

一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。

优点:

1、类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本。

2、通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗。

缺点:

1、虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。

2、实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的

索引举例:(用树结构做索引)

左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址。

MySQL索引结构实例分析

为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在一定的复杂度内获取到相应数据,从而快速的检索出符合条件的记录。

索引结构(树)

如何通过索引加快数据库表的查询速度呢?为了方便讲解,我们限定于数据库表只包含下面这样两个查询需求:

1、select* from user where id=1234;

2、select *from user where id>1234 and id<2345;(按区间)

为什么用树,而不用哈希表

哈希表按值查询的性能很好,时间复杂度是O(1),但它不能支持按照区间快速查找数据,因此无法满足要求。同理,尽管平衡二叉查找树查询性能很高,时间复杂度为O(logn),而且对树进行中序遍历,可以输出有序的数据序列,但也无法满足按照区间快速查找数据的需求。

为了支持按照区间快速查找数据,我们对二叉查找树进行改造,将二叉查找树的叶子节点用链表串起来,如果要查找某个区间的数据,只需要用区间的起始值,在树中进行查找,当定位到有序链表中的某个节点之后,再从这个节点开始顺着有序链表往后遍历,直到有序链表中的节点数据值大于区间终止值为止。

MySQL索引结构实例分析

又因为树上的很多操作的时间复杂程度与树的高度成正比,降低的树的高度,就能减少磁盘IO操作。因此我们把索引构建成m叉树(m>2),详细介绍可看后文。

BTree索引

在介绍B+树之前,先来了解一下B树。

MySQL索引结构实例分析

1、初始化介绍

一颗b树,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块1包含数据项17和35,包含指针P1、P2、P3。P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。

注意:

真实的数据只存在于叶子节点,即3、5、9、10、13、15、28、29、36、60、75、79、90、99。(而且是多条数据组成的数据区间:3~ 5,… … ,90~ 99)

非叶子节点不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。

2、查找过程

如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计,通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时内存中做二分查找找到29,结束查询,总计三次IO。

B+Tree索引

B+树和B树类似,B+树是B树的改进版。 即:m叉查找树与有序链表构建成的树就是B+树,也就是要存储的树索引

MySQL索引结构实例分析

如图:B+树和B树的主要区别有以下两点:

1、B+树的叶子节点用链表来串联。 查找某个区间的数据,只需要用区间的起始值,在树中进行查找,当定位到有序链表中的某个节点之后,再从这个节点开始顺着有序链表往后遍历,直到有序链表中的节点数据值大于区间终止值为止。

2、B+树中的任何节点都不存储真实数据,只是用来索引。 B树直接通过叶子节点获取到数据;而B+树每个叶子节点存储数据行的键值和地址信息,当查询到某个叶子节点时,通过叶子节点的地址找到真实的数据信息。

聚簇索引与非聚簇索引

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。 术语‘聚簇’表示数据行和相邻的键值聚簇的存储在一起。

聚簇索引的好处:

按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不不用从多个数据块中提取数据,所以节省了大量的io操作。

聚簇索引的限制:

1、对于mysql数据库目前只有innodb数据引擎支持聚簇索引,而Myisam并不支持聚簇索引。

2、由于数据物理存储排序方式只能有一种,所以每个Mysql的表只能有一个聚簇索引。一般情况下就是该表的主键。

3、为了充分利用聚簇索引的聚簇的特性,所以innodb表的主键列尽量选用有序的顺序id,而不建议用无序的id,比如uuid这种。

如下图,左侧的索引就是聚簇索引,因为数据行在磁盘的排列和索引排序保持一致。

MySQL索引结构实例分析

索引分类

单值索引

即一个索引只包含单个列,一个表可以有多个单列索引

随表一起建索引:CREATE TABLE customer (id INT(10) UNSIGNED  AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),PRIMARY KEY(id),KEY (customer_name)); 单独建单值索引:CREATE  INDEX idx_customer_name ON customer(customer_name);  删除索引:DROP INDEX idx_customer_name  on customer;

少数索引

索引列的值必须少数,但允许有空值

随表一起建索引:CREATE TABLE customer (id INT(10) UNSIGNED  AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),  PRIMARY KEY(id),  KEY (customer_name),  UNIQUE (customer_no));  单独建少数索引:CREATE UNIQUE INDEX idx_customer_no ON customer(customer_no);  删除索引:DROP INDEX idx_customer_no on customer ;

主键索引

设定为主键后数据库会自动建立索引,innodb为聚簇索引

随表一起建索引:CREATE TABLE customer (id INT(10) UNSIGNED  AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),  PRIMARY KEY(id) );   CREATE TABLE customer2 (id INT(10) UNSIGNED   ,customer_no VARCHAR(200),customer_name VARCHAR(200),  PRIMARY KEY(id) );  单独建主键索引:ALTER TABLE customer  add PRIMARY KEY customer(customer_no);   删除建主键索引:ALTER TABLE customer  drop PRIMARY KEY ;   修改建主键索引:必须先删除掉(drop)原索引,再新建(add)索引

复合索引

即一个索引包含多个列

随表一起建索引:CREATE TABLE customer (id INT(10) UNSIGNED  AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),  PRIMARY KEY(id),  KEY (customer_name),  UNIQUE (customer_name),  KEY (customer_no,customer_name)); 单独建索引:CREATE  INDEX idx_no_name ON customer(customer_no,customer_name);  删除索引:DROP INDEX idx_no_name  on customer ;

性能分析

索引创建场景

哪些情况需要创建索引

1、主键自动建立少数索引

2、频繁作为查询条件的字段应该创建索引

3、查询中与其它表关联的字段,外键关系建立索引

4、单键/组合索引的选择问题, 组合索引性价比更高

5、查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度

6、查询中统计或者分组字段

哪些情况不要创建索引

1、表记录太少

2、经常增删改的表或者字段 原因:提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件

3、Where条件里用不到的字段不创建索引

4、过滤性不好的不适合建索引

感谢各位的阅读,以上就是“MySQL索引结构实例分析”的内容了,经过本文的学习后,相信大家对MySQL索引结构实例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

文章标题:MySQL索引结构实例分析,发布者:亿速云,转载请注明出处:https://worktile.com/kb/p/22250

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
亿速云的头像亿速云认证作者
上一篇 2022年9月1日 下午11:17
下一篇 2022年9月1日 下午11:18

相关推荐

  • mysql数据库拉链表是什么

    拉链表产生背景 在数据仓库的数据模型设计过程中,经常会遇到这样的需求: 1、数据量比较大; 2、表中的部分字段会被update,如用户的地址,产品的描述信息,订单的状态等等; 3、需要查看某一个时间点或者时间段的历史快照信息,比如,查看某一个订单在历史某一个时间点的状态,比如,查看某一个用户在过去某…

    2022年9月24日
    96100
  • 如何查询mysql中所有表

    查询mysql数据库中所有表的方法:1、执行“mysql -u root -p”命令并输入密码来登录mysql数据库服务器;2、执行“USE 数据库名;”命令来切换到指定数据库;3、执行“show tables;”或“SHOW FULL TABLES;”命令,会以表格形式列出mysql数据库中的所有…

    2022年9月22日
    4.7K00
  • 如何分析web漏洞利用中的弱口令

    一,定义 弱口令(weak password) 没有严格和准确的定义,通常认为容易被别人(他们有可能对你很了解)猜测到或被破解工具破解的口令均为弱口令。弱口令指的是仅包含简单数字和字母的口令,例如“123”、“abc”等,因为这样的口令很容易被别人破解,从而使用户的计算机面临风险,因此不推荐用户使用…

    2022年9月24日
    1.7K00
  • css中id选择符的标识是哪个

    在css中,id选择符的标识是“#”,可以为标有特定id属性值的HTML元素指定特定的样式,语法结构“#ID值 {属性 : 属性值;}”。ID属性在整个页面中是少数不可重复的;ID属性值不要以数字开头,数字开头的ID在Mozilla/Firefox浏览器中不起作用。 本教程操作环境:windows7…

    2022年9月22日
    58000
  • WordPress插件WooCommerce任意文件删除漏洞怎么解决

    技术细节 WordPress的权限处理机制主要是通过给不同角色提供不同的功能来实现的,当商铺管理员角色被定义之后,它便会给这个角色分配edit_users功能,这样他们就可以直接管理商铺的客户账号了。整个权限分配过程发生在插件插件饿的安装过程当中。woocommerce/includes/class…

    2022年8月30日
    61800
  • IDEA类存在但找不到如何解决

    1.刷新maven项目 2.清理idea缓存 3.maven clean install 4.重新bulid 5.如果使用了lombok插件开启之后重新build 6.maven依赖冲突导致 1.打开当前maven模块或者,父类模块对应的pom,哪个模块有冲突进入那个模块!2.ctlr+alt+sh…

    2022年9月21日
    1.7K00
  • MyBatisPlus QueryWrapper多条件查询及修改方法是什么

    gt、ge、lt、le、isNull、isNotNull 大于 > 例: gt(“age”, 18) &rarr; age > 18 ge 大于等于 >= 例: ge(“age”, 18) &rarr; age &gt…

    2022年9月21日
    1.6K00
  • cdr钢笔工具如何使用

    cdr钢笔工具的使用方法和技巧: 1、打开cdr,在左边工具栏就能找到钢笔工具。 2、选中后,点击起始点并点击第二个点就能绘制一条线。 3、如果按住键盘“shift”键,就可以绘制一条水平的直线了。 4、如果按住第二个点,拖动鼠标,就可以绘制曲线。 5、沿着蓝色线拖动鼠标,可以继续绘制曲线。 6、如…

    2022年8月30日
    77900
  • 电脑0xc0000011如何解决

    0xc0000011修复方法: 方法一: 1、首先我们需要查看是否是软件问题,开机时按住“F8”直到进入系统修复界面。 2、接着在其中选择“最后一次正确的配置”回车进入。 3、如果我们无法进入系统,那么说明就不是安装的软件或驱动等问题。 方法二: 1、这时候就需要采用系统盘进行修复了。 2、如果我们…

    2022年9月18日
    63800
  • Redis集群与扩展知识点分析

    Redis的高可用 1.为什么要高可用 防止单点故障,造成整个集群不可用 实现高可用通常的做法是将数据库复制多个副本以部署在不同的服务器上,其中一台挂了也可以继续提供服务 Redis实现高可用有三种部署模式:主从模式,哨兵模式,集群模式 2.主从模式 主节点负责读写操作 从节点只负责读操作 从节点的…

    2022年9月15日
    69300
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部