当前位置: 首页 > article >正文

MySQL索引和其底层数据结构介绍

索引在项目中非常常见,它是一种帮助MySQL高效获取数据的数据结构,主要用来提高数据检索效率,降低数据库的I/O成本。同时,索引列可以对数据进行排序,降低数据排序的成本,也能减少CPU的消耗。就像是书的目录,能帮助读者快速找到所需内容。
下面从索引的类型、优缺点、创建和使用等方面详细介绍:

  1. 索引类型
    • 普通索引:最基本的索引类型,没有唯一性限制。它可以加速对数据的查询操作。在MySQL中,使用CREATE INDEX语句创建普通索引,例如:CREATE INDEX idx_name ON table_name (column_name);,这就在table_name表的column_name列上创建了名为idx_name的普通索引。
    • 唯一索引:该索引要求索引列的值必须唯一,但允许有空值。创建唯一索引可以确保数据的唯一性约束。创建语句如:CREATE UNIQUE INDEX idx_unique ON table_name (column_name);
    • 主键索引:特殊的唯一索引,用于唯一标识表中的每一行记录,不允许有空值。在创建表时,可以指定主键索引,例如:CREATE TABLE table_name (id INT PRIMARY KEY, column1 VARCHAR(255)); ,这里的id列就是主键索引。
    • 全文索引:主要用于在文本类型的列中进行全文搜索。MySQL的全文索引支持InnoDB和MyISAM存储引擎。例如:CREATE FULLTEXT INDEX idx_fulltext ON table_name (text_column);,在table_name表的text_column列上创建全文索引。不过,全文索引的使用场景相对较少,且性能优化需要谨慎处理。
    • 组合索引:也叫复合索引,是在多个列上创建的索引。使用组合索引时,需要注意列的顺序,遵循最左前缀原则。例如:CREATE INDEX idx_multiple ON table_name (column1, column2, column3); ,这是在table_name表的column1column2column3列上创建的组合索引。在查询时,如果条件包含column1,或者同时包含column1column2等,该组合索引都可能被使用。
  2. 索引的优点
    • 提高查询效率:大大减少了数据库查询时需要扫描的数据量,加快数据检索速度,提升查询性能。比如在一个有大量用户数据的表中,通过对user_id列建立索引,根据user_id查询用户信息时,能快速定位到对应记录,而不用全表扫描。
    • 保证数据唯一性:唯一索引和主键索引能确保特定列或列组合的值在表中是唯一的,维护了数据的完整性和一致性。
    • 实现表与表之间的关联:在多表关联查询时,索引可以加快表之间的连接速度。外键约束通常借助索引来提高查询性能,使得关联查询更加高效。
  3. 索引的缺点
    • 占用存储空间:索引本身需要占用一定的磁盘空间,随着数据量的增加,索引占用的空间也会增大。在高并发写入场景下,索引维护会产生额外的I/O开销,影响写入性能。
    • 影响更新性能:当对表中的数据进行插入、更新或删除操作时,数据库不仅要更新数据本身,还要更新相应的索引,这会增加操作的时间成本,降低数据更新的效率。
  4. 索引的创建原则
    • 选择合适的列:在经常用于查询条件、排序、连接操作的列上创建索引。例如,在WHERE子句、ORDER BY子句、JOIN操作涉及的列上。
    • 避免过度索引:创建过多索引会增加存储和维护成本,降低写入性能。只有在必要的情况下才创建索引,权衡查询和更新操作的性能。
    • 注意列顺序(组合索引):对于组合索引,将选择性高(基数大,即列中不同值的数量多)的列放在前面,遵循最左前缀原则,以提高索引的使用效率。
  5. 查看和删除索引
    • 查看索引:可以使用SHOW INDEX FROM table_name;语句查看指定表上的索引信息,包括索引名称、索引类型、涉及的列等。
    • 删除索引:使用DROP INDEX index_name ON table_name;语句删除指定表上的索引。在删除索引时要谨慎,确保不会对查询性能产生负面影响。

MySQL索引的底层主要使用了B-Tree(B树)、B+Tree(B+树)和哈希表(Hash)这几种数据结构,不同的存储引擎支持的索引结构有所不同,以下是详细介绍:

B-Tree(B树)

  • 结构特点
    • B树是一种自平衡的多路搜索树,它的每个节点可以有多个子节点。每个节点包含多个键值和指向子节点的指针。
    • 所有叶子节点位于同一层,这保证了查询的稳定性,无论查找哪个键值,所需的磁盘I/O次数大致相同。
    • 节点中的键值按升序排列,左子树的所有键值小于当前节点的键值,右子树的所有键值大于当前节点的键值。
  • 在MySQL中的应用
    • 早期的MyISAM存储引擎在实现索引时采用过B树结构。在B树索引中,每个节点既存储键值,也存储对应的数据记录指针。
    • 当进行范围查询时,B树需要在多个节点之间进行遍历,可能会涉及较多的磁盘I/O操作,效率相对较低。

B+Tree(B+树)

  • 结构特点
    • B+树是B树的一种变体,同样是自平衡的多路搜索树。它的非叶子节点只存储键值和指向子节点的指针,不存储数据记录指针;而叶子节点存储了所有的数据记录指针,并且叶子节点之间通过指针相连,形成一个有序链表。
    • 所有的数据查询最终都要访问到叶子节点,因此查询的时间复杂度是固定的,为O(log n),其中n是节点数量。
  • 在MySQL中的应用
    • InnoDB和MyISAM存储引擎主要使用B+树作为索引的底层数据结构。在InnoDB中,主键索引(聚簇索引)的叶子节点存储了完整的数据记录,而辅助索引的叶子节点存储的是主键值,通过主键值再去主键索引中查找完整数据。
    • 由于B+树的叶子节点之间有指针相连,非常适合范围查询。在进行范围查询时,可以沿着叶子节点的链表顺序访问,减少了磁盘I/O次数,提高了查询效率。

B树和B+树的主要区别在于
B树的非叶子节点和叶子节点都存放数据,而B+树的所有数据只出现在叶子节点,这使得B+树在查询时效率更稳定。
B+树在进行范围查询时效率更高,因为所有数据都在叶子节点,并且叶子节点之间形成了双向链表。

哈希表(Hash)

  • 结构特点
    • 哈希表是一种根据键值直接访问内存存储位置的数据结构,通过哈希函数将键值映射到一个固定大小的数组索引上。
    • 哈希表的查找、插入和删除操作的平均时间复杂度为O(1),效率非常高。
  • 在MySQL中的应用
    • Memory存储引擎支持哈希索引。哈希索引适用于等值查询,例如WHERE column = value这种类型的查询。
    • 哈希索引的缺点是不支持范围查询,因为哈希函数将键值映射到不同的位置,无法直接根据键值的大小关系进行范围查找。同时,哈希冲突的处理会增加额外的开销。

综上所述,B+树由于其适合范围查询和有序遍历的特点,成为了MySQL中最常用的索引底层数据结构,而哈希索引则在特定的等值查询场景中发挥作用。

其他索引相关问题:

什么是聚簇索引什么是非聚簇索引?
聚簇索引是指数据与索引放在一起,B+树的叶子节点保存了整行数据,通常只有一个聚簇索引,一般是由主键构成。
非聚簇索引则是数据与索引分开存储,B+树的叶子节点保存的是主键值,可以有多个非聚簇索引,通常我们自定义的索引都是非聚簇索引。

什么是回表查询吗?
回表查询是指通过二级索引找到对应的主键值,然后再通过主键值查询聚簇索引中对应的整行数据的过程。

什么叫覆盖索引吗?
覆盖索引是指在SELECT查询中,返回的列全部能在索引中找到,避免了回表查询,提高了性能。使用覆盖索引可以减少对主键索引的查询次数,提高查询效率。

MySQL超大分页怎么处理?
超大分页通常发生在数据量大的情况下,使用LIMIT分页查询且需要排序时效率较低。可以通过覆盖索引和子查询来解决。首先查询数据的ID字段进行分页,然后根据ID列表用子查询来过滤只查询这些ID的数据,因为查询ID时使用的是覆盖索引,所以效率可以提升。

索引创建原则有哪些?
创建索引的原则包括:
表中的数据量超过10万以上时考虑创建索引。
选择查询频繁的字段作为索引,如查询条件、排序字段或分组字段。
尽量使用复合索引,覆盖SQL的返回值。
如果字段区分度不高,可以将其放在组合索引的后面。
对于内容较长的字段,考虑使用前缀索引。
控制索引数量,因为索引虽然可以提高查询速度,但也会影响插入、更新的速度。

什么情况下索引会失效?
索引可能在以下情况下失效:
没有遵循最左匹配原则。
使用了模糊查询且%号在前面。
在索引字段上进行了运算或类型转换。
使用了复合索引但在中间使用了范围查询,导致右边的条件索引失效。


http://www.kler.cn/a/551138.html

相关文章:

  • 国产编辑器EverEdit - 如虎添翼的功能:快速选择
  • AutoGPT:突破性人工智能工具,赋能自动化写作与任务执行的未来
  • 用于可靠工业通信的5G-TSN集成原型:基于帧复制与消除可靠性的研究
  • 基于Springboot+Vue前后端分离的农场投入品运营线上管理系统设计与实现+万字文档+指导搭建视频
  • Logo语言的图形用户界面
  • Linux:expr命令、测试条件表达式、正则表达式入门教程
  • day9手机创意软件
  • 【Linux】动静态库的制作与原理
  • Deepseek-R1推理模型API接入调用指南 ChatGPT Web Midjourney Proxy 开源项目接入Deepseek教程
  • matlab 三维时频图绘制
  • 如何在不依赖函数调用功能的情况下结合工具与大型语言模型
  • Linux线程库与线程库封装
  • 解析 WebGPU 中 device.createBuffer 的参数意义
  • 初阶c语言(函数练习)
  • STM32 CubeMx配置串口收发使用DMA并调用Idle模式(一)
  • Ubuntu如何利用.ibd文件恢复MySQL数据?
  • 单例模式的使用方式
  • 【Python】循环语句详解:for语句、while语句
  • JavaScript设计模式 -- 观察者模式
  • 如何将ubuntu下的一个目录,保存目录结构为一个git仓库并上传