MySQL索引(InnoDB)

MySQL索引(InnoDB)

一:数据在表中的组织存放方式

索引组织表

在InnoDB存储引擎中,表都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表。在InnoDB存储引擎表中,每张表都有个主键,如果在创建表时没有显式地定义主键,则InnoDB存储引擎会按如下方式选择或创建主键:

  • 首先判断表中是否有非空的唯一索引(Unique NOT NULL),如果有,则该列即为主键。
  • 如果不符合上述条件,InnoDB存储引擎自动创建一个6字节大小的指针。
    另外,当表中有多个非空唯一索引时,InnoDB存储引擎将选择建表时第一个定义的非空唯一索引为主键。这里需要非常注意的是,主键的选择根据的是定义索引的顺序,而不是建表时列的顺序。

InnoDB逻辑存储结构

从InnoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间
中,称之为表空间(Tablespace),表空间又由段(Segment)、区(Extent)、页(Page)组成。
MySQL索引(InnoDB)

  1. 表空间:
    表空间可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都存放在表空间中。在默认情况下InnoDB存储引擎有一个共享表空间ibdata1,即所有数据都存放在这个表空间内。若启用了参数innodb_file_per_table,则每张表内的数据可以单独放到一个表空间内。
  2. 段:
    表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。因为InnoDB存储引擎表是索引组织的,因此数据即索引,索引即数据。那么数据段存放的是B+树的叶子节点(Leaf node segment),索引段存放的是B+树的非叶子节点(Non-leaf node segment)。
  3. 区:
    区是由连续页组成的空间,在任何情况下每个区的大小都为1MB。为了保证区中页的连续性,InnoDB存储引擎一次从磁盘申请4~5个区。在默认情况下,InnoDB存储引擎页的大小为16KB,即一个区中有64个连续的页。
  4. 页:
    页是InnoDB磁盘管理的最小单位,在InnoDB存储引擎中,默认每个页的大小为16KB。从InnoDB 1.2.x版本开始,可以通过参数innodb_page_size将页的大小设置为4K、8K、16K。若设置完成,则所有表中页的大小都为innodb_page_size,不可以对其再次进行修改。需要注意的是,==B+树索引只能找到记录所在的页,但是并不能定位到记录在页中的具体位置,这需要通过page directory的二分查找得到具体的记录。==然而,由于通过B+树索引得知记录所在的页后,InnoDB存储引擎会将页加载到缓冲池中,二分查找在内存中完成,速度很快,因此一般会忽略这个查询的开销。

二:索引的分类

  1. B+树索引
    B+树是为磁盘或其他直接存取辅助设备设计的一种平衡查找树。在B+树中,所有记录节点都是按键值的大小顺序存放在同一层的叶子节点上,由各叶子节点指针进行连接。在数据库中,B+树的高度一般都在2~4层,这也就是说查找某一键值的行记录时最多只需要2到4次IO。这很不错,因为当前一般的机械磁盘每秒至少可以做100次IO,2~4次的IO意味着查询时间只需0.02~0.04秒。在数据库中,B+树索引还可以分为聚集索引和辅助索引,但不管是聚集索引还是辅助索引,其内部都是B+树的,即高度平衡的,叶子节点存放着所有的数据。聚集索引与辅助索引不同的是,叶子节点存放的是否是一整行的信息。
  2. 哈希索引
    InnoDB存储引擎支持的哈希索引是自适应的,InnoDB存储引擎会根据表的使用情况自动为表生成哈希索引,不能人为干预是否在一张表中生成哈希索引。
  3. 全文索引
    全文索引是一种特殊类型的索引,它查找的是文本中的关键词,而不是直接比较索引中的值。全文搜索和其他几类索引的匹配方式完全不一样。它有许多需要注意的细节,如停用词、词干和复数、布尔搜索等。全文索引更类似于搜索引擎做的事情,而不是简单的WHERE条件匹配。

对于哈希索引来说,由于它是自适应的,我们不用过多的去考虑。而全文索引:例如模糊查询 like…,对于这种业务我们最好是引入搜索引擎(例如:Elasticsearch)来操作,这样效果会更好。 所以我们把重点放在B+树索引上。

三:B+ 树索引

聚集索引(聚簇索引)

聚集索引就是按照每张表的主键构造一棵B+树,同时叶子节点中存放的即为整张表的行记录数据,也将聚集索引的叶子节点称为数据页。聚集索引的这个特性决定了索引组织表中数据也是索引的一部分。同B+树数据结构一样,每个数据页都通过一个双向链表来进行链接。由于实际的数据页只能按照一棵B+树进行排序,因此每张表只能拥有一个聚集索引。在多数情况下,查询优化器倾向于采用聚集索引,因为聚集索引能够在B+树索引的叶子节点上直接找到数据。此外,由于定义了数据的逻辑顺序,聚集索引能够特别快地访问针对范围值的查询。
MySQL索引(InnoDB)

辅助索引

对于辅助索引,叶子节点并不包含行记录的全部数据。叶子节点除了包含键值以外,每个叶子节点中的索引行中还包含了一个书签。该书签用来告诉InnoDB存储引擎哪里可以找到与索引相对应的行数据。由于InnoDB存储引擎表是索引组织表,因此InnoDB存储引擎的辅助索引的书签就是相应行数据的聚集索引键。

辅助索引的存在并不影响数据在聚集索引中的组织,因此每张表上可以有多个辅助索引。当通过辅助索引来寻找数据时,InnoDB存储引擎会遍历辅助索引并通过叶级别的指针获得指向主键索引的主键,然后再通过主键索引来找到一个完整的行记录。举例来说,如果在一棵高度为3的辅助索引树中查找数据,那需要对这棵辅助索引树遍历3次找到指定主键,如果聚集索引树的高度同样为3,那么还需要对聚集索引树进行3次查找,最终找到一个完整的行数据所在的页,因此一共需要6次逻辑IO访问以得到最终的一个数据页。
MySQL索引(InnoDB)

四:B+ 树索引的使用

索引选择

一张表上可以建立多个索引,在执行查询时具体选择哪一个索引,这是由SQL优化器来决定的。我们可以通过分析执行计划,来查看SQL优化器选择了哪一个索引。
MySQL索引(InnoDB)
通常,SQL优化器选择的索引都是高效的。但如果你确定要显示指定个索引来完成查询,则可以使用索引提示功能来实现这样的需求。

建议MySQL走索引I
SELECT * FROM 表名 use index(I) WHERE ......;

强制MySQL走索引I
SELECT * FROM 表名 force index(I) WHERE ......;

联合索引

覆盖索引

五:哈希索引

六:全文索引

上一篇:mysql中的聚集索引、非聚集索引、稀疏索引、稠密索引


下一篇:MYSQL索引机制