深入分析MySQL索引与磁盘读取原理

索引

索引是对数据库表中一列或者多列数据检索时,为了加速查询而创建的一种结构。可以在建表的时候创建,也可以在后期添加。
USER表中有100万条数据,现在要执行一个查询"SELECT * FROM USER where ID=999999",如果没有索引,查询的时候MySQL会从第一行开始遍历,直到ID等于999999的这一行被找到为止。如果在ID列上创建索引,MySQL不需要任何扫描,直接在索引里面找999999,就可以得知这一行的位置。

  1. 结构:索引可以采用不同的数据结构,最常见的是B+树索引。B+树索引是一种树状结构,其中根节点连接到多个中间节点,最终指向叶子节点,叶子节点包含实际的数据行或指向数据行的引用。
  2. 唯一性:索引可以是唯一的,也可以包含重复值。唯一索引确保索引列中的值是唯一的,而非唯一索引可以包含重复值。
  3. 创建:索引是通过数据库管理系统的SQL语句创建的。通常,你可以使用CREATE INDEX语句来创建索引。在创建索引时,需要指定要在哪些列上创建索引以及使用哪种索引类型。
  4. 维护:随着数据表的更新(插入、更新、删除操作),索引也需要不断维护以保持其准确性。维护包括插入新的索引项、更新现有的索引项和删除不再符合条件的索引项。
  5. 覆盖索引:覆盖索引是一种包含了查询所需的所有列的索引。它可以避免回表操作,因为索引本身包含了所需的数据。
  6. 聚簇索引:聚簇索引是一种特殊类型的索引,它决定了数据行的物理存储顺序。一个表只能有一个聚簇索引,通常是主键索引。
  7. 非聚簇索引:非聚簇索引是其他非主键索引,它不决定数据行的物理存储顺序,通常需要回表操作来获取完整的数据。

B 树

B 树又叫平衡多路查找树,每个节点可以包含多个子节点,因此 B 树的高度比较低,从而查找过程中 I/O 次数比较少。当插入或删除操作破坏了B树的平衡时,节点可能会分裂成两个节点或合并成一个节点,以维持平衡。
根节点:最顶端的节点,就是要最开始遍历的节点,一般存在缓存中。
内部节点:内部节点是除叶子节点和根节点之外的所有节点
叶节点:没有子节点,也没有指向子节点的指针,所有叶节点在同一层。
每个节点包含了 键 key、指针 p 指向子节点、以及数据 data
504706238.png
阶是表示所有节点中子节点个数的最大值,一般用 m 表示。
一棵m阶的B 树的特性如下:

  • 每一个节点最多有 m 个子节点
  • 每一个非叶子节点(除根节点)最少有 ceil(m/2)(向上取整) 个子节点
  • 如果根节点不是叶子节点,那么它至少有两个子节点
  • k 个子节点的非叶子节点拥有 k − 1 个键
  • 所有的叶子节点都在同一层

B+树

B+树是一个平衡的多叉树,和 B 树一样有三中节点,根节点,内部节点,叶节点。B+树的非叶节点只存储键值,数据都存储在叶节点中,所有叶节点都在同一层,形成一个单向链表,对于主键的排序查找和范围查找速度非常快。

-432284220.png

内部节点,p 指向子节点,k 关键字
叶子节点,k 是关键字,d 指向包含关键字 k 的磁盘的文件块,p 指向下一个相邻的叶节点,也就是叶节点通过 p 来连接成一个链表。

B+树作为索引的原因

B+树每个节点可以拥有多个子节点,相比于二叉树B树的分支更多,减少了树的高度,提高了操作效率。红黑树也是二叉的平衡树,高度比B树高,树的查找性能取决于树的高度,高度越高对IO操作次数越多,在内存中,红黑树比B树性能好,在文件系统种,B树比红黑树好。

B树和B+树的区别

1、B 树非叶子节点和叶子节点都存储数据,因此查询数据时,时间复杂度最好为O(1),最坏为 O(logn)。B+树只在叶子节点存储数据,非叶子节点存储关键字,且不同非叶子节点的关键字可能重复,因此查询数据时,时间复杂度固定为O(logn)。
2、 如果完成一次遍历操作,B树通过中序遍历。 B+树叶子节点之间用链表相互连接,因而只需要扫描叶子节点的链表就可以完成一次遍历操作。
3、B树的优势是当要查找的值恰好处于一个非叶子节点时,查找该节点就会成功并结束查询,不需要到达叶节点。B+树由于非叶子节点只是索引部分,无论查找成功与否,都要到达叶节点。
4、 在 B 树中,被删除的项可能出现在非叶结点中。我们必须从包含被删除项的子树中选择正确的值来作为替代。在 B+树中,被删除的项总是出现在叶结点中。
5、B+树非叶子节点上是不存储数据的,仅存储键值,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖。

B+树和 B 树 范围查询

在B+树中,所有数据都存储在叶子节点上,而且这些数据按键值的顺序有序排列。这意味着相关数据通常存储在相邻的叶子节点上,从而形成了连续的数据范围。在范围查询时,可以轻松地扫描连续的数据块,而不必跳跃到不相邻的数据块,从而减少了磁盘访问的延迟。
B+树的内部节点通常只包含键值和指向子节点的指针,而不包含数据本身。这减少了访问内部节点的开销,因为在B树中,内部节点可能包含部分数据。在范围查询中,B+树内部节点的减少访问可以显著减少不必要的磁盘访问。B 树 总是要从根节点向下遍历子树查找到包含左边界数据的节点,再进行中序遍历找到包含右边界数据的节点。每遍历一次节点,就要进行 I/O 。

聚簇索引

聚簇索引是数据库表中的一种特殊索引,它决定了表中数据行的物理存储顺序。在一个表上只能有一个聚簇索引(因为表中的数据默认只能有一种存储顺序),这个索引定义了数据行在磁盘上的排列顺序。
如果聚簇索引的键值按顺序排列,那么数据行也会按顺序存储在磁盘上,而不是随机存储的。这种情况下,范围查询和顺序扫描性能通常会非常好,因为数据行在磁盘上是紧密排列的,减少了磁盘寻道时间。 比如在订单表中,如果在下单时间上创建了聚簇索引,那么存储在订单表中的数据,默认是按下单时间存储的。
聚簇索引通常适用于需要支持范围查询和顺序扫描操作的数据,以及具有紧凑、顺序存储的数据,比如时间、日期、ID、序列号、金融数据等。

非聚簇索引

与聚簇索引相对应的是非聚簇索引。非聚簇索引只包含索引键值和指向实际数据行的指针,而不决定数据行在磁盘上的存储顺序。当使用非聚簇索引执行范围查询时,可能需要进行更多的磁盘读取,因为数据行的物理存储顺序不一定与索引顺序一致。 如果需要快速查找单个行或具有高度变化的索引键值,非聚簇索引可能更合适。

聚簇索引磁盘读取过程

  1. 聚簇索引的键值决定了数据行的物理存储顺序。这意味着具有相似或连续键值的数据行在磁盘上也是相邻存储的,而不同键值的数据行可能在磁盘上分散存储。
  2. 在机械硬盘上,读取数据需要进行磁盘寻道操作,当数据行在磁盘上按顺序排列时,寻道时间较低,因为数据行紧密排列在相邻的磁道上。
    3.具有聚簇索引的表通常在范围查询方面表现出色。由于相关数据行在磁盘上是连续存储的,范围查询可以有效地从头到尾扫描数据行,而无需频繁进行磁盘寻道。
    4.如果一个表上有非聚簇索引,这些索引通常会指向具体的数据行。非聚簇索引的使用可能需要额外的磁盘读取,因为它们可能引导查询从索引到数据行的跳转,导致更多的磁盘寻道操作。
    5.在数据库设计中,需要考虑查询需求和性能优化来决定是否使用聚簇索引。如果数据库表的主要操作是范围查询或顺序扫描,那么聚簇索引通常是更好的选择。但如果需要快速查找单个数据行或具有高度变化的索引键值,非聚簇索引可能更适合。

索引查询过程

考虑一个简单的查询过程,假设我们有一个名为"employees"的员工表,其中"EmployeeID"是聚簇索引列。

  1. 查询条件:用户执行查询,例如查找"EmployeeID"等于1001的员工记录。
  2. 聚簇索引查找:数据库管理系统使用聚簇索引(B+树)来查找满足查询条件的记录。在B+树索引中,我们从根节点开始导航,逐级向下,直到找到叶子节点,其中包含了EmployeeID为1001的键值。
  3. 数据行定位:一旦索引找到了匹配的键值(1001),数据库管理系统使用聚簇索引的物理存储顺序直接定位到实际数据行的位置。由于聚簇索引的键值与数据行的键值相匹配,所以可以精确地找到数据行的位置。
  4. 数据行访问:数据库管理系统直接从数据表中的物理存储位置访问或检索数据行,而无需额外的磁盘访问。这是因为聚簇索引的物理存储顺序与索引键值的顺序一致,从而提供了快速的数据访问。
  5. 数据行返回:最后,查询返回EmployeeID等于1001的员工记录。

回表

是数据库查询优化中的一个术语,指的是在使用非聚簇索引进行查询时,数据库需要额外访问数据表来获取完整的数据行。回表中的非聚簇索引通常会返回主键索引的值,然后根据主键索引再次查询数据。这是因为非聚簇索引的叶子节点通常包含指向数据行的主键值,而不是实际的数据。
查询过程

  1. 索引键值查询:首先,数据库管理系统使用非聚簇索引来查找匹配查询条件的索引键值。
  2. 获取主键值:在索引叶子节点中找到匹配的索引键值后,数据库会获取主键索引的值。这通常是数据行的主键列的值。
  3. 再次查询数据:一旦获取了主键值,数据库管理系统将使用这个主键值来执行另一次查询,但这次是在主键索引上执行。这个查询将定位到实际数据行,从而获取完整的数据。

索引数据存储位置

在数据库中,索引通常存储在磁盘上,并且与数据表的物理存储分开:

  1. 系统表空间:某些数据库管理系统(如Oracle)将索引存储在系统表空间中。系统表空间是一个专门用于存储数据库系统元数据(包括索引定义)的区域。
  2. 用户表空间:其他数据库管理系统(如MySQL和PostgreSQL)将索引存储在用户表空间中。每个用户可以有一个或多个表空间,用于存储表、索引和其他对象。
  3. 独立文件:在某些情况下,数据库管理系统允许将索引存储在独立的文件中。这通常是为了管理索引的物理存储位置,以优化性能或数据管理。
  4. 内存中:一些数据库管理系统会将索引的一部分或整个索引缓存在内存中,以提高查询性能。这些内存索引通常是对常用的索引进行缓存,以加速查询。

索引建立过程

  1. 选择索引列:首先,选择一个或多个表中的列作为索引列。通常,你会选择那些经常用于查询条件的列,以提高查询性能。
  2. 索引类型:确定要创建的索引类型,例如B+树索引、哈希索引、全文索引等。大多数数据库系统使用B+树索引,因为它们对各种查询类型都有效。
  3. 创建索引:执行数据库管理系统提供的CREATE INDEX语句来创建索引。这将触发数据库系统执行以下操作:
    • 数据扫描:遍历数据表中的所有数据行。
    • 键值提取:从每个数据行中提取索引列的键值。
    • 索引插入:将键值插入到索引结构中,按照选择的索引类型进行排序。
  4. 维护索引:随着数据表的变化(插入、更新、删除操作),索引也需要不断维护以保持其准确性。这包括在数据插入时插入新的索引项,数据更新时更新索引项,以及在数据删除时删除相应的索引项。

示例:
假设有一个名为"employees"的员工表,其中包含以下列:EmployeeID(员工ID)、FirstName(名字)、LastName(姓氏)、Department(部门)等。现在我们希望在"LastName"列上创建一个B+树索引。

sqlCopy code
-- 创建B+树索引
CREATE INDEX idx_lastname ON employees (LastName);

这个示例中,我们使用SQL的CREATE INDEX语句在"employees"表的"LastName"列上创建了一个B+树索引,名为"idx_lastname"。数据库管理系统将执行数据扫描,提取"LastName"列的键值,并按照B+树结构进行排序和插入。随着数据表的更改,索引将进行维护,以保持其准确性。
一旦索引创建完成,查询操作在"LastName"列上将更快速,因为数据库管理系统可以使用这个索引来快速定位并检索数据行,而不必扫描整个表。这提高了查询性能,特别是在大型数据表上。

物理存储顺序

指的是数据在计算机磁盘或内存等物理存储介质上的排列顺序。它表示数据元素在物理存储介质上的实际位置,这一位置通常与数据元素在逻辑上的排列顺序(例如,按照键值或索引的顺序)不一定完全一致。
数据通常以二进制形式存储在磁盘、内存或其他存储介质上。物理存储顺序对于数据的读取和访问性能至关重要,因为它影响了数据访问时的磁盘寻道时间、内存访问时间等因素。

  1. 顺序存储:如果数据在物理存储介质上按照逻辑顺序存储,即相邻数据元素依次排列,这通常会提高范围查询和顺序扫描的性能。
  2. 随机存储:如果数据在物理存储介质上以随机顺序存储,数据元素之间可能会散布在不同的位置,导致更多的磁盘寻道和读取操作,降低性能。
  3. 磁盘寻道:在机械硬盘上,数据的物理存储顺序影响了磁盘寻道时间。数据元素越接近,磁头的移动距离就越小,寻道时间越短。
  4. 内存存储:在内存中,物理存储顺序对于缓存性能也很重要。如果数据在内存中紧密存储,缓存命中的机会更大,从而提高读取性能。

数据库和磁盘

-1561414663.png

机械硬盘结构

1、盘片:磁盘通常由多个金属或玻璃盘片组成,每个盘片有两个磁性表面。这些盘片被堆叠在一起,共享一个中心轴。
2、磁道:每个盘片的表面被划分成多个同心圆状的磁道,这些磁道沿盘片的半径方向分布。
3、扇区:每个磁道又被分成若干扇区,通常是物理存储的最小单元。数据存储在这些扇区中,每个扇区有一个唯一的地址。硬盘的第一个扇区,叫做引导扇区。
4、簇:操作系统对硬盘进行读写时需要用到文件系统把硬盘的扇区组合成簇,并建立文件和树形目录制度,使操作系统对其访问和查找变得容易,这是因为操作系统直接对数目众多的扇区进行寻址会十分麻烦。
5、柱面:柱面是垂直于盘片的直线,连接相同位置上不同盘片上的磁道。多个盘片上的磁道构成一个柱面,它们具有相同的半径位置。
6、主轴:磁盘的主轴是一个旋转轴,用于旋转盘片。盘片通常以高速旋转,例如每分钟数千转。
7、磁头:每个磁性表面上悬浮着一个磁头,用于读取和写入数据。这些磁头通常非常接近盘片表面,以便进行高精度的数据访问。
8、 电机驱动器:电机驱动器用于旋转盘片,使其保持高速旋转。它通常位于磁盘的内部结构。
9、 控制器:磁盘控制器是磁盘的智能部分,负责控制磁头的移动、管理数据访问、寻道和定位,以及与计算机系统通信。
10、 缓存:一些磁盘具有内置缓存,用于临时存储数据以提高读写性能。这是一个较小但更快速的存储区域,用于加速数据传输。

寻道和旋转时间

1、寻道 读取或写入数据时,磁盘通常需要将磁头移动到正确的磁道上,这个过程称为寻道。这个过程需要一定的时间,通常以毫秒为单位。
2、旋转 在寻道完成后,磁盘需要等待所需的扇区旋转到磁头的位置,以便进行读取或写入操作。盘片旋转到特定扇区的位置也是需要时间的。

数据块

磁盘的数据通常被划分为块(或者页),有助于减少这些时间。块是存储和检索数据的最小单位。每个块通常包含一个固定数量的字节,通常是4KB或更大,每个块通常包含一个文件的一部分或多个文件的整个内容。在InnoDB存储引擎中,数据页的大小通常为16KB,这个数值可以根据系统需求进行配置。

访问模式

1、 顺序访问,数据存在连续的磁盘块上。当 进行 I/O时,第一块可能需要寻道,后续相邻的磁道会被连续访问,这种情况下,操作系统会预先的读取连续的块,减少 I/O 次数。
2、 随机访问,数据存在随机的磁盘块上,每一次 I/O 都要进行一次寻道

磁盘运作原理

当磁盘被使用时,驱动马达使磁盘以很高的恒定速度旋转(通常为每秒60、90或120转,也可达到每秒250转)。磁头恰好位于盘片表面的上方。对于现在的磁盘,扇区大小一般为512字节,每一个盘片有约50000100000条磁道,每条磁盘有15个盘片。内侧的磁道(离转轴近的地方)长度较短,内侧每磁道大约包含5001000个扇区,而外侧每磁道大约包含10002000个扇区。
一张磁盘通常包括很多个盘片,每个盘片的每一面都有一个磁头,磁头通过在盘片上移动来访问不同的磁道。所有磁道的磁头安装在一个称为磁盘臂的单独装置上,并且一起移动。安装在转轴上的所有磁盘盘片和安装在磁盘臂上的所有磁头统称为磁头-磁盘装置。因为所有盘片上的磁头一起移动,所以当某一个盘片的磁头在第i条磁道上时,所有其他盘片的磁头也都在各自盘片的第i条磁道上。因此,所有盘片的第i条磁道合在一起称为第 i 个柱面。磁盘工作时,通过反转磁性物质磁化的方向,磁头将信息磁化存储到扇区中。
数据库管理系统或文件系统维护一个数据页到物理块(磁盘块)的映射表。这个映射表记录了每个数据页对应的物理块的位置,通常包括磁盘块的地址或偏移量。当需要访问或修改特定数据页时,B+树结构或数据库管理系统会查找映射表,找到相应的物理块。然后,它执行磁盘读写操作,读取或写入该磁盘块上的数据。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

selenium xpath定位

selenium-xpath定位 <span style"background-color:#2d2d2d"><span style"color:#cccccc"><code class"language-javascript">element_xpath <span style"color:#67cdcc"></span> driver<span styl…

嵌入式养成计划-48----QT--信息管理系统:百川仓储管理

一百二十二、信息管理系统&#xff1a;百川仓储管理 122.1 UI界面 122.2 思路 客户端&#xff1a; 用户权限有两种类型&#xff0c;一种是用户权限&#xff0c;一种是管理员权限&#xff0c;登录时服务器端会根据数据库查询到的此用户名的权限返回不同的结果&#xff0c;客户…

CodeWhisperer 的正确使用

1、重点&#xff1a; 重点1&#xff1a; 推出 Amazon Bedrock。这项新服务允许用户通过 API 访问来自 AI21 Labs、Anthropic、Stability AI 和亚马逊的基础模型。&#xff08;Anthropic 就是之前跟 ChatGPT 掰手腕的 Claude 的模型。Stability AI 就是 Stable Diffusion 背后的…

IP 地址冲突检测工具

IP 冲突是一个术语&#xff0c;用于表示同一网络或子网中尝试使用相同 IP 地址的两个或多个设备的状态&#xff0c;这可能会导致发往特定主机的通信与其他主机混淆&#xff0c;因为两者都使用相同的 IP&#xff0c;为了避免这种情况&#xff0c;某些主机在发生 IP 冲突时会失去…

MySQL中的多列子查询

-- 多列子查询 -- 如何查询与WOARD 的部门和岗位完全相同的所有雇员(并且不含smith本人) -- (字段1&#xff0c;字段2...) (select 字段1&#xff0c;字段2 from ...) -- 分析&#xff1a; 1. 得到smith的部门和岗位 SELECT deptno,job FROM empWHERE ename WARD; -- 2.使…

大数据-玩转数据-Flume

一、Flume简介 Flume提供一个分布式的,可靠的,对大数据量的日志进行高效收集、聚集、移动的服务,Flume只能在Unix环境下运行。Flume基于流式架构,容错性强,也很灵活简单。Flume、Kafka用来实时进行数据收集,Spark、Flink用来实时处理数据,impala用来实时查询。二、Flume…

挑战100天 AI In LeetCode Day05(热题+面试经典150题)

挑战100天 AI In LeetCode Day05&#xff08;热题面试经典150题&#xff09; 一、LeetCode介绍二、LeetCode 热题 HOT 100-72.1 题目2.2 题解 三、面试经典 150 题-73.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站&#xff0c;提供各种算法和数据结构的题目&am…

JVM GC 垃圾收集器

文章目录 System.gc()内存溢出&#xff08;OOM&#xff09;OOM 的原因 内存泄漏垃圾回收的并行与并发安全点与安全区域 Java 中的引用分类强引用&#xff08;Strong Reference&#xff09;软引用&#xff08;Soft Reference&#xff09;弱引用&#xff08;Weak Reference&#…

基于SSM的小区物业管理系统设计与实现

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

Flink SQL Regular Join 、Interval Join、Temporal Join、Lookup Join 详解

Flink ⽀持⾮常多的数据 Join ⽅式&#xff0c;主要包括以下三种&#xff1a; 动态表&#xff08;流&#xff09;与动态表&#xff08;流&#xff09;的 Join动态表&#xff08;流&#xff09;与外部维表&#xff08;⽐如 Redis&#xff09;的 Join动态表字段的列转⾏&#xf…

Linux 入门

Linux 入门 1&#xff1a;linux 用户 root 用户 &#xff1a;也叫超级用户&#xff0c;UID0&#xff0c;其权限最高。系统用户&#xff1a;也叫虚拟用户&#xff0c;UID 1-999普通用户: UID1000-60000, 可以登录系统,操作自己目录下的文件. 1.1:用户操作命令 切换用户: su …

STM32外部中断大问题

问题&#xff1a;一直进入中断&#xff0c;没有触发信号&#xff0c;也一直进入。 描述&#xff1a;开PA0为外部中断&#xff0c;刚刚很好&#xff0c;一个触发信号一个中断&#xff0c;中断函数没有丢&#xff0c;也没有抢跑&#xff0c;开PA1为外部中断也是&#xff0c;都很好…

nfs配置

1.NFS介绍 NFS就是Network File System的缩写&#xff0c;它最大的功能就是可以通过网络&#xff0c;让不同的机器、不同的操 作系统可以共享彼此的文件。 NFS服务器可以让PC将网络中的NFS服务器共享的目录挂载到本地端的文 件系统中&#xff0c;而在本地端的系统中来看&#…

C++初阶 | [二] 类和对象(上)

摘要&#xff1a;class&#xff0c;成员函数&#xff0c;成员变量&#xff0c;类的大小&#xff0c;this 指针 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象…

CSS 网页布局

网页布局有很多种方式&#xff0c;一般分为以下几个部分&#xff1a;头部区域、菜单导航区域、内容区域、底部区域&#xff1a; 1&#xff09;、头部区域位于整个网页的顶部&#xff0c;一般用于设置网页的标题或者网页的logo。 <style> body { margin: 0; } /* 头部样…

【Redis】list常用命令内部编码使用场景

文章目录 前置知识列表类型的特点 命令LPUSHLPUSHXRPUSHRPUSHXLRANGELPOPRPOPLINDEXLREMLINSERTLTRIMLSETLLEN 阻塞版本命令BLPOPBRPOP 命令总结内部编码测试内部编码 使用场景消息队列分频道的消息队列 模拟栈和队列 前置知识 列表类型是⽤来存储多个有序的字符串&#xff0c…

软件测试|Monkey基本参数介绍

说到android移动端稳定性测试&#xff0c;大家通常会想到android系统自动Monkey小猴子&#xff0c;通过Monkey命令模拟用户触摸点击屏幕、滑动、系统按键等操作来对设备上的app进行压力测试&#xff0c;来测试应用的稳定性和健壮性。 下面就说说monkey常用参数的用法~~ 1、-h…

Spring笔记(二)(黑马)(AOP面向切面编程)

01、AOP 简介 1.1 AOP的概念 AOP&#xff0c;Aspect Oriented Programming&#xff0c;面向切面编程&#xff0c;是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象&#xff0c;一个对象包括静态的属性信息&#xff0c;包括动态的方法信息等。而AOP是横向的对不同事物的…

spdk用户态块层详解

先通过回顾内核态的通用块层来详细介绍SPDK通用块层&#xff0c;包括通用块层的架构、核心数据结构、数据流方面的考量等。最后描述基于通用块层之上的两个特性&#xff1a;一是逻辑卷的支持&#xff0c;基于通用块设备的Blobstore和各种逻辑卷的特性&#xff0c;精简配置&…

C# OpenCvSharp 去除文字中的线条

效果 中间过程效果 项目 代码 using OpenCvSharp; using System; using System.Drawing; using System.Windows.Forms; using static System.Net.Mime.MediaTypeNames;namespace OpenCvSharp_Demo {public partial class frmMain : Form{public frmMain(){InitializeComponent…