索引原理

78 阅读6分钟

索引的概述

myssql官方度低索引的定义:索引是mysql存储引擎用于快速查找记录的一种数据结构

  • 索引是一种特殊的数据文件

     myisam存储引擎:数据文件和索引文件是分开的,索引文件中保存的是数据记录的地址。
      
     innodb存储引擎:表数据本身就是按照B+tree组织的索引结构。 .ibd文件就是数据+索引存储文件。
      
      
    
  • 索引是一种数据结构

索引是一个独立的 物理的数据结构,它是由一个表中的一个字段或多个字段组合而成
  • mysql 中默认使用的b+tree结构管理索引

一颗B+Tree可以存放多少数据?

mysql B+Tree的数据结构图

截屏2024-08-20 22.47.27.png

  • mysql中一个页的大小为16kb, 指针节点大小为 6b,假设id是bigInt的为8b。那么根节点可以存放 161024/(8+6)=1170个索引,那么第二层最多有1170个索引页,可存储 11701170=1369234个索引,第三层 数据层 每一行记录算1kb,每页可存储 16个
  • 那么高度为三的b+tree 可存放 16*1024/(8+6)117016=21907744条数据 2000多万条

hash索引

聚簇索引

聚簇索引的概述

 索引分类:
 1.按照字段特性分类:主键索引 普通索引 前缀索引
 2.按照数据结构分类:B+Tree索引,Hash索引
 3.按照物理存储方式分类:聚簇索引  辅助索引(二级索引)
 

聚簇索引的定义:

聚簇索引也叫聚集索引,它实际上并不是一种单独的索引类型,而是一种数据存储方式,聚簇索引的叶子节点保存了一行记录的所有列信息。也就是说,聚簇索引的叶子节点中,包含了一个完整的记录行。 若定义了主键,则主键索引就成为聚簇索引;若没有定义主键,则表中第一个非空唯一的列作为聚簇索引;如果都不满足,InnoDB引擎会创建一个隐藏列row-id作为聚簇索引。因此,InnoDB引擎的表要求必须有聚簇索引(主键索引)。

聚簇索引的特点

在于它确定了表中数据的物理顺序,这使得查询操作更加高效,因为查询可以直接定位到数据的位置,而不需要进行额外的数据查找或转换。与非聚簇索引相比,聚簇索引具有更快的检索速度,因为它避免了行物理顺序与索引顺序不匹配的问题。此外,聚簇索引还可以支持二级索引(辅助索引或非主键索引)的创建,这些二级索引通常用于提高查询效率,但它们占用的空间比聚簇索引小很多。在InnoDB存储引擎中,一个表只能有一个聚簇索引,但可以创建多个二级索引。当进行索引覆盖扫描时,可以直接从B+Tree中获取所需的值,避免了通过主键查询主键索引(回表查询)获取数据的额外步骤,从而提高了查询效率‌

非聚簇索引也叫辅助索引、普通索引,它的叶子节点只包含一个主键值,通过非聚簇索引查找记录要先找到主键,然后通过主键再到聚簇索引中找到对应的记录行,这个过程被称为回表。

什么是回表?回表带来的问题

MySQL中的"回表"是指在使用索引查询数据时,如果需要查询的数据不在索引节点上,那么就需要通过索引上的地址(如行指针或者ROWID)去查询实际的数据行。这个过程称为"回表"。

回表通常发生在索引的"覆盖"情况下,即查询的列都包含在创建索引时指定的列中。如果查询的列没有完全包含在索引中,那么即使是索引扫描,MySQL也需要回表查询实际的数据行。

举个例子,假设有一个表users,包含列(id, name, age, address),并且有一个索引(name)。

如果执行查询SELECT name FROM users WHERE name = 'Alice';,因为name列已经在索引中,这个查询不需要回表。

但如果执行查询SELECT name, age FROM users WHERE name = 'Alice';,即使age不在索引(name)中,由于索引覆盖了查询的列,MySQL仍然可以从索引中获取所需数据,不需要回表。

如果查询SELECT name FROM users WHERE age > 30;,即使name在索引中,由于查询条件涉及到age列,age不在索引(name)中,MySQL也需要回表查询实际的数据行。

  • 为了减少回表,可以考虑以下方法:

  • 优化查询,使用索引覆盖更多的列。

  • 创建多列索引,如(name, age),这样就可以覆盖更多的查询列。

  • 使用覆盖索引,即只使用索引进行查询,不查询实际的数据行,而是返回索引的列即可。

回表访问的IO次数取决于查询的具体情况和数据库的结构。‌

在MySQL数据库中,回表操作是指通过索引查找数据记录的过程,每次通过索引找到一条记录后,都需要回到数据表中进行数据读取。这个过程涉及到的IO次数取决于查询的方式和数据库的结构。例如,如果通过二级索引执行查询,每次获取到一条二级索引记录时,就会立刻对其进行回表操作,这意味着每获取一条记录就可能进行一次IO操作。如果查询涉及到多个不同的记录,那么回表的次数就会相应增加。此外,如果查询需要回表的数据量很大,比如通过用户名索引进行查询,可能需要回表多次才能获取到所有相关的数据记录。

具体到IO次数,假设每个磁盘块的大小为16kb,而一个磁盘块可以指向1600行数据,那么在一个三层B+树中,通过用户名索引进行查询,每次回表可能需要3次IO,这是因为B+树的层级结构导致的。如果查询的记录数为50万条,那么总的回表次数将是50万次,因此总的IO次数将是50万乘以3,即150万次IO。

综上所述,回表访问的IO次数并不是固定的,它取决于查询的具体情况,包括索引的类型、查询的数据量以及数据库的结构等因素。在设计和优化查询时,应考虑到这些因素,以减少不必要的回表操作,从而提高查询效率‌

自增id如何选择