索引的数据结构(MySql高级)

索引的数据结构

  • 为什么使用索引
  • 什么是索引
  • 索引的优缺点
    • 优点
    • 缺点
  • 常见索引概念
    • 聚簇索引
    • 二级索引(辅助索引, 非聚簇索引)
    • InnoDB的B+树索引的注意事项
  • MyISAM 与 InnoDB 对比
  • 索引的代价

为什么使用索引

索引是存储引擎用于快速找到数据记录的一种数据结构,就好比一本教科书的目录部分,通过目录中找到对应文章的页码,便可快速定位到需要的文章. MySQL中也是一样的道理,进行数据查找时,首先查看查询条件是否命中某条索引,符合则通过索引查找相关数据,如果不符合则需要全表扫描,即需要一条一条地查找记录,直到找到与条件符合的记录.

什么是索引

MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。
索引的本质:索引是数据结构. 可以简单理解为“排好序的快速查找数据结构”,满足特定查找算法. 这些数据结构以某种方式指向数据, 这样就可以在这些数据结构的基础上实现高级查找算法.
索引是在存储引擎中实现的, 因此每种存储引擎的索引不一定完全相同,并且每种存储引擎不一定支持所有索引类型. 同时,存储引擎可以定义每个表的最大索引数最大索引长度. 所有存储引擎支持每个表至少16个索引,总索引长度至少为256字节. 有些存储引擎支持更多的索引数和更大的索引长度.

索引的优缺点

优点

  1. 提高数据检索的效率,降低 数据库的IO成本 ,这也是创建索引最主要的原因。
  2. 通过创建唯一索引,可以保证数据库表中每一行 数据的唯一性
  3. 在实现数据的 参考完整性方面,可以 加速表和表之间的连接 。换句话说,对于有依赖关系的子表和父表联合查询时, 可以提高查询速度。
  4. 在使用分组和排序子句进行数据查询时,可以显著 减少查询中分组和排序的时间 ,降低了CPU的消耗。

缺点

  1. 创建索引和维护索引要 耗费时间 ,并 且随着数据量的增加,所耗费的时间也会增加。
  2. 索引需要占 磁盘空间 ,除了数据表占数据空间之 外,每一个索引还要占一定的物理空间, 存储在磁盘上 ,如果有大量的索引,索引文件就可能比数据文 件更快达到最大文件尺寸。
  3. 虽然索引大大提高了查询速度,同时却会 降低更新表的速度 。当对表 中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度。 因此,选择使用索引时,需要综合考虑索引的优点和缺点。

因此,选择使用索引时,需要综合考虑索引的优点和缺点
索引可以提高查询的速度,但是会影响插入记录的速度。这种情况下,最好的办法是先删除表中的索引,然后插入数据,插入完成后再创建索引。

常见索引概念

索引按照物理实现方式,索引可以分为 2 种:聚簇(聚集)和非聚簇(非聚集)索引。我们也把非聚集索引称为二级索引或者辅助索引。

聚簇索引

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式(所有的用户记录都存储在了叶子结点),也就是所谓的索引即数据, 数据即索引.
术语"聚簇"表示当前数据行和相邻的键值聚簇的存储在一起
特点:

  • 使用记录主键值的大小进行记录和页的排序,这包括三个方面的含义:
    • 页内的记录是按照主键的大小顺序排成一个单向链表
    • 各个存放用户记录的页也是根据页中用户记录的主键大小顺序排成一个双向链表
    • 存放目录项记录的页分为不同的层次,在同一层次中的页也是根据页中目录项记录的主键大小顺序排成一个双向链表
  • B+树的 叶子节点 存储的是完整的用户记录。
    所谓完整的用户记录,就是指这个记录中存储了所有列的值(包括隐藏列)。
  • 我们把具有这两种特性的B+树称为聚簇索引,所有完整的用户记录都存放在这聚簇索引的叶子节点处。这种聚簇索引并不需要我们在MySQL语句中显式的使用INDEX 语句去创建,InnDB存储引擎会自动的为我们创建聚簇索引

image.png
优点:

  • 数据访问更快,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快
  • 聚簇索引对于主键的排序查找范围查找速度非常快
  • 按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不用从多 个数据块中提取数据,所以节省了大量IO操作

缺点:

  • 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
  • 更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新
  • 二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据

二级索引(辅助索引, 非聚簇索引)

如果我们想以别的列作为搜索条件该怎么办?肯定不能是从头到尾沿着链表依次遍历记录一遍。
答案:我们可以多建几颗B+树,不同的B+树中的数据采用不同的排列规则。比方说我们用c2列的大小作为数据页、页中记录的排序规则,再建一课B+树,效果如下图所示:
image.png
这个B+树与上边介绍的聚簇索引有几处不同:

  • 使用记录c2列的大小进行记录和页的排序,这包括三个方面的含义

    1. 页内的记录是按照c2列的大小顺序排成一个单向链表。
    2. 各个存放用户记录的页也是根据页中记录的c2列大小顺序排成一个双向链表存放目录项记录的页分为不同的层次,在同一层次中的页也是根据页中目录项记录的c2列大小顺序排成一个双向链表。
    
  • B+树的叶子节点存储的并不是完整的用户记录,而只是c2列+主键这两两个列的值。

  • 目录项记录中不再是主键+页号的搭配,而变成了c2列+页号的搭配。

所以如果我们现在想通过c2列的值查找某些记录的话就可以使用我们网刚刚建好的这个B+树了。以查找c2列的值为4的记录为例,查找过程如下:

  1. 确定 目录项记录页根据根页面,也就是页44,可以快速定位到目录项记录所在的页为页42(因为2<4<9)。
  2. 通过目录项记录页确定用户记录真实所在的页。在页42中可以快速定位到实际存储用户记录的页,但是由于c2列并没有唯一性约束,所以c2列值为4的记录可能分布在多个数据页中,又因为2<4=4,所以确定实际存存储用户记录的页在页34和页35中。
  3. 在真实存储用户记录的页中定位到具体的记录。到页34和页35中定位到具体的记录。
  4. 但是这个B+树的叶子节点中的记录只存储了c2和c1(也就就是主键)两个列,所以我们必须再根据主键值去聚簇索引中再查找一遍完整的用户记录。

聚簇索引与非聚簇索引的原理不同,在使用上也有一些区别:

  1. 聚簇索引的叶子结点存储的就是我们的数据记录, 非聚簇索引的叶子节点存储的是数据位置。非聚簇索引不会影响数据表的物理存储顺序。
  2. 一个表只能有一个聚簇索引,因为只能有一种排序存储的方式,但可以有多个非聚簇索引,也就是多个索引目录提供数据检索。
  3. 使用聚簇索引的时候,数据的查询效率高,但如果对数据进行插入,删除,更新等操作,效率会比非聚簇索引低。

InnoDB的B+树索引的注意事项

  1. 根页面位置万年不动

实际上B+树的形成过程是这样的:

  • 每当为某个表创建一个B+树索引(聚簇索引不是人为创建的,默认就有)的时候,都会为这个索引创建一个根节点页面。最开始表中没有数据的时候,每个B+树索引对应的根节点中即没有用户记录,也没有目录项记录。
  • 随后向表中插入用户记录时,先把用户记录存储到这个根节点中。
  • 当根节点中的可用 空间用完时继续插入记录,此时会将根节点中的所有记录复制到一个新分配的页,比如 页a中,然后对这个新页进行页分裂的操作,得到另一个新页,比如页b。这时新插入的记录根据键值(也就是聚簇索引中的主键值,二级索引中对应的索引列的值)的大小就会被分配到页a或者页b中,而根节点便升级为存储目录项记录的页。

这个过程特别注意的是:一个B+树索引的根节点自诞生之日起,便不会再移动。这样只要我们对某个表建议一个索引,那么它的根节点的页号便会被记录到某个地方。然后凡是 InnoDB存储引擎需要用到这个索引的时候,都会从哪个固定的地方取出根节点的页号,从而来访问这个索引。

  1. 一个页面最少储存两条数据

MyISAM 与 InnoDB 对比

MyISAM的索引方式都是“非聚簇”的,与InnoDB包含1个聚簇索引是不同的。小结两种引擎中索引的区别:
① 在InnoDB存储引擎中,我们只需要根据主键值对聚簇索引进行一次查找就能找到对应的记录,而在 MyISAM 中却需要进行一次回表操作,意味着MyISAM中建立的索引相当于全部都是 二级索引 。
② InnoDB的数据文件本身就是索引文件,而MyISAM索引文件和数据文件是分离的 ,索引文件仅保存数据记录的地址
③ InnoDB的非聚簇索引data域存储相应记录**主键的值 ,而MyISAM索引记录的是地址 **。换句话说, InnoDB的所有非聚簇索引都引用主键作为data域。
MyISAM的回表操作是十分快速的,因为是拿着地址偏移量直接到文件中取数据的,反观InnoDB是通过获取主键之后再去聚簇索引里找记录,虽然说也不慢,但还是比不上直接用地址去访问。
⑤ InnoDB要求表 必须有主键 ( MyISAM可以没有 )。如果没有显式指定,则MySQL系统会自动选择一个 可以非空且唯一标识数据记录的列作为主键。如果不存在这种列,则MySQL自动为InnoDB表生成一个隐 含字段作为主键,这个字段长度为6个字节,类型为长整型。

索引的代价

空间上的代价
每建立一个索引都要为它建立一棵B+树,每一棵B+树的每一个节点都是一个数据页,一个页默认会 占用 16KB 的存储空间,一棵很大的B+树由许多数据页组成,那就是很大的一片存储空间。
时间上的代价
每次对表中的数据进行 增、删、改 操作时,都需要去修改各个B+树索引。而且我们讲过,B+树每 层节点都是按照索引列的值 从小到大的顺序排序 而组成了 双向链表 。不论是叶子节点中的记录,还 是内节点中的记录(也就是不论是用户记录还是目录项记录)都是按照索引列的值从小到大的顺序 而形成了一个单向链表。而增、删、改操作可能会对节点和记录的排序造成破坏,所以存储引擎需 要额外的时间进行一些 记录移位 , 页面分裂 、 页面回收 等操作来维护好节点和记录的排序。如果 我们建了许多索引,每个索引对应的B+树都要进行相关的维护操作,会给性能拖后腿。

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

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

相关文章

基于SSM的网上购物商城设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

Vue知识总结-下

VUE-组件间通信 组件的自定义事件 概述&#xff1a;是一种组件间通信的方式,适用于&#xff1a;子组件>父组件使用场景&#xff1a;A是父组件,B是子组件,B给A传递数据,那么需要在A组件中绑定自定义事件(事件的回调也在A中)使用步骤 绑定自定义事件&#xff1a; 第一种方式…

Python展示 RGB立方体的二维切面视图

代码实现 import numpy as np import matplotlib.pyplot as plt# 生成 24-bit 全彩 RGB 立方体 def generate_rgb_cube():# 初始化一个 256x256x256 的三维数组rgb_cube np.zeros((256, 256, 256, 3), dtypenp.uint8)# 填充立方体for r in range(256):for g in range(256):fo…

压缩编码之不同缩放参数对重建图像质量的影响的python实现——JPEG变换编码不同压缩率的模拟

原理 JPEG&#xff08;Joint Photographic Experts Group&#xff09;是一种常用的图像压缩标准&#xff0c;它通过采用离散余弦变换&#xff08;DCT&#xff09;和量化来实现图像的压缩。 离散余弦变换&#xff08;DCT&#xff09;&#xff1a; JPEG首先将图像分割成8x8的块…

LeetCode 160: 两个链表的相交节点 - 优雅解法

LeetCode 160: Intersection of Two Linked Lists 题目描述 给定两个单链表 headA 和 headB 的头节点&#xff0c;返回它们相交的节点。如果两个链表没有相交&#xff0c;返回 null。 示例: 输入&#xff1a;intersectVal 8, listA [4,1,8,4,5], listB [5,6,1,8,4,5], sk…

【安全策略】前端 JS 安全对抗浏览器调试方法

一、概念解析 1.1 什么是接口加密 如今这个时代&#xff0c;数据已经变得越来越重要&#xff0c;网页和APP是主流的数据载体。而如果获取数据的接口没有设置任何的保护措施&#xff0c;那么数据的安全性将面临极大的威胁。不仅可能造成数据的轻易窃取和篡改&#xff0c;还可能…

高通平台开发系列讲解(USB篇)DWC3控制USB速率

文章目录 一、设备树二、相关结构体三、最大速率设置四、当前速率设置沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本文主要介绍高通平台USB DWC3控制USB速率。 一、设备树 目录:msm-4.14/arch/arm64/boot/dts/qcom/sdxprairie-usb.dtsi dwc3@a600000 {compatibl…

通过myBatis将sql语句返回的值自动包装成一个java对象(2)

1.之前我们是如何执行一个sql语句自动包装成一个java对象呢&#xff1f; 1.创建一个mapper.xml&#xff0c;定义 执行的语句名字 和 包装成什么类 2.在总的配置文件里申明这个mapper 3.在java里通过sqlSession执行mapper里定义好的内容 我们还可以使用另一种方法实现第三步。现…

java如何修改windows计算机本地日期和时间?

本文教程&#xff0c;主要介绍&#xff0c;在java中如何修改windows计算机本地日期和时间。 目录 一、程序代码 二、运行结果 一、程序代码 package com;import java.io.IOException;/**** Roc-xb*/ public class ChangeSystemDate {public static void main(String[] args)…

快速更改flutter已有项目的项目名称和id等

如果你使用了别人已有的仓库模板或者想更改现有项目的名称&#xff0c;是一件非常繁琐的工作&#xff0c;需要修改全平台的文件还是相当麻烦的&#xff0c;所以这里推荐一个小工具&#xff0c;可以帮助大家快速实现更改项目名称的目的&#xff0c;这个工具地址&#xff1a;rena…

任务14:使用MapReduce提取全国每年最低/最高气温

任务描述 知识点&#xff1a; 使用MapReduce提取数据 重 点&#xff1a; 开发MapReduce程序统计每年每个月的最低气温统计每年每个月的最高气温 内 容&#xff1a; 使用IDEA创建一个MapReduce项目开发MapReduce程序使用MapReduce统计每年每个月的最低气温使用MapReduce…

正则表达式和爬虫

目录 一、正则表达式&#xff1a; 作用&#xff1a; 字符类&#xff08;只匹配一个字符&#xff09; 细节 预定义字符字符&#xff08;只匹配一个字符&#xff09; 细节 数量词 二、爬虫 Pattern Matcher 要点说明 一、正则表达式&#xff1a; 作用&#xff1a; 1、校验字符…

pytorch集智-5手写数字识别器-卷积神经网络

1 简介 简称&#xff1a;CNN&#xff0c;convolutional neural network 应用场景&#xff1a;图像识别与分类&#xff08;CNN&#xff09;&#xff0c;看图说话&#xff08;CNNRNN&#xff09;等 优越性&#xff1a;和多层感知机相比&#xff0c;cnn可以识别独特的模式&…

Kubernetes (K8S) 3 小时快速上手 + 实践

1. Kubernetes 简介 k8s即Kubernetes。其为google开发来被用于容器管理的开源应用程序&#xff0c;可帮助创建和管理应用程序的容器化。用一个的例子来描述&#xff1a;"当虚拟化容器Docker有太多要管理的时候&#xff0c;手动管理就会很麻烦&#xff0c;于是我们便可以通…

二叉树:从基础结构到高级遍历技术

. 个人主页&#xff1a;晓风飞 专栏&#xff1a;数据结构|Linux|C语言 路漫漫其修远兮&#xff0c;吾将上下而求索 文章目录 引言结构定义接口需求构建二叉树销毁二叉树计算节点和叶子的数量二叉树节点个数二叉树叶子节点个数二叉树第k层节点个数 二叉树查找值为x的节点二叉树的…

立白科技集团:研发安全推动数字化蜕变,日化业务再上新高度

立白科技集团成立于1994年&#xff0c;是我国日化行业的领军企业&#xff0c;致力于成为一家“品牌引领、数字经营、富有创新、富有活力”的智慧服务型企业。从2018年开始&#xff0c;立白科技集团加速数字化转型&#xff0c;打造数据和业务中台&#xff0c;并建立toB和toC平台…

修改和调试 onnx 模型

1. onnx 底层实现原理 1.1 onnx 的存储格式 ONNX 在底层是用 Protobuf 定义的。Protobuf&#xff0c;全称 Protocol Buffer&#xff0c;是 Google 提出的一套表示和序列化数据的机制。使用 Protobuf 时&#xff0c;用户需要先写一份数据定义文件&#xff0c;再根据这份定义文…

【C语言】指针知识点笔记(2)

目录 一、野指针 二、assert断言 三、指针的使用和传址调用 四、数组名的理解 五、使用指针访问数组 一、野指针 二、assert断言 三、指针的使用和传址调用 四、数组名的理解 五、使用指针访问数组

Vue响应式系统(二)

Vue响应式系统(一) 六、嵌套的effect与effect栈。 什么场景会用到effect嵌套呢&#xff1f;听我娓娓道来。 就用Vue.js来说吧&#xff0c;Vue.js的渲染函数就是在effect中执行的&#xff1a; /*Foo组件*/ const Foo {render() {return /*.....*/} }// effect中执行Foo组件中…

kubectl与 jq的另外一些用法

背景&#xff1a; 在日常运维工作中&#xff0c;我们需要管理和操作大量的配置文件&#xff0c;这在使用 Kubernetes 集群管理应用时尤为常见。Kubernetes 提供了一个名为 ConfigMap 的资源对象&#xff0c;它用于存储应用的配置信息。有时&#xff0c;我们需要查找哪些 Confi…