索引是一种用于快速查询行的数据结构,就像一本书的目录就是一个索引,如果想在一本书中找到某个主题,一般会先找到对应页码。在mysql中,存储引擎用类似的方法使用索引,先在索引中找到对应值,然后根据匹配的索引记录找到对应的行。

我们首先了解一下索引的几种类型和索引的结构。

索引类型

B树

大多数存储引擎都支持B树索引。b树通常意味着所有的值都是按顺序存储的,并且每一个叶子也到根的距离相同。B树索引能够加快访问数据的速度,因为存储引擎不再需要进行全表扫描来获取数据。下图就是一颗简单的B数。

B树的查询流程:

如上图我要从找到E字母,查找流程如下:

获取根节点的关键字进行比较,当前根节点关键字为M,E拿到关键字D和G,D拿到E和F,因为E=E 所以直接返回关键字和指针信息(如果树结构里面没有包含所要查找的节点则返回null);通过指针信息取出这条记录的所有信息;

B+树

下图为B+树的结构,B+树是B树的升级版,我们可以观察一下,B树和B+树的区别是什么?

B+树和B树的区别是:

B树的节点中没有重复元素,B+树有。B树的中间节点会存储数据指针信息,而B+树只有叶子节点才存储。B+树的每个叶子节点有一个指针指向下一个节点,把所有的叶子节点串在了一起。

从下图我们可以直观的看到B树和B+树的区别:紫红色的箭头是指向被索引的数据的指针,大红色的箭头即指向下一个叶子节点的指针。

我们假设被索引的列是主键,现在查找主键为5的记录,模拟一下查找的过程:

B树,在倒数第二层的节点中找到5后,可以立刻拿到指针获取行数据,查找停止。

B+树,在倒数第二层的节点中找到5后,由于中间节点不存有指针信息,则继续往下查找,在叶子节点中找到5,拿到指针获取行数据,查找停止。

B+树每个父节点的元素都会出现在子节点中,是子节点的最大(或最小)元素。叶子节点存储了被索引列的所有的数据。

那B+树比起B树有什么优点呢?

了解了B+树的结构之后,我们对一张具体的表做分析:

create table Student(
 last_name varchar(50) not null, 
 first_name varchar(50) not null, 
 birthday date not null, 
 gender int(2) not null, 
 key(last_name, first_name, birthday)
);

对于表中的每一行数据,索引中包含了name,birthday列的值。下图显示了该索引的结构:

索引对多个值进行排序的依据是create table语句中定义索引时列的顺序,即如果名字相同,则根据生日来排序。

B+树的结构决定了这种索引对以下类型的查询有效:

一些限制:

哈希索引

哈希索引,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。如果多个列的哈希值相同,索引会以链表的方式存放多个指针记录到同一个哈希条目中。

因为索引自身只存储对应的哈希值,所以索引的结构十分紧凑,哈希索引查找的速度非常快。但是哈希索引也有它的限制:

聚集索引(clusterd index)

每个存储引擎为InnoDB的表都有一个特殊的索引,叫聚集索引。聚集索引并不是一种单独的索引类型,而是一种数据存储方式。当表有聚集索引的时候,它的数据行实际上存放在叶子页中。一个表不可能有两个地方存放数据,所以一个表只能有一个聚集索引

因为是存储引擎负责实现索引,因此不是所有的存储引擎都支持聚集索引。InnoDB表中聚集索引索引列就是主键,所以聚集索引也叫主键索引

例如下面这张InnoDB表:

create table Student(
 id int(11) primary key auto_increment,
 last_name varchar(50) not null, 
 first_name varchar(50) not null, 
 birthday date not null
);

聚集索引(主键索引)的结构如下图:

hash索引和btree索引_索引_sphinx 主索引和增量索引

这是一课B+树,它的叶子页包含了行的全部数据,节点页只包含了索引列(即主键)。

二级索引(secondary indexes)

对于InnoDB表,在非主键列的其他列上建的索引就是二级索引(因为聚集索引只有一个)。二级索引可以有0个,1个或者多个。二级索引和聚集索引的区别是什么呢?二级索引的节点页和聚集索引一样,只存被索引列的值,而二级索引的叶子页除了索引列值,还存这一列对应的主键值。

InnoDB和MyISAM的数据分布对比

sphinx 主索引和增量索引_hash索引和btree索引_索引

以下表为例,我们看下InnoDB和MyISAM是如何存储这个表的:

create table layout_test(
 col1 int(11) primary key, 
 col2 int(11) not null, 
 key(col2)
);

InnoDB表的数据分布

聚集索引(主键索引)分布如下:

sphinx 主索引和增量索引_索引_hash索引和btree索引

可以看到,叶子节点存储了整个表的数据,而不是只有索引列,每个叶子节点包含了主键值、事务ID、用于事务和MVCC的回滚指针以及所有的剩余列(col2)。

二级索引分布如下:

hash索引和btree索引_索引_sphinx 主索引和增量索引

二级索引的叶子节点中存储的不是“行指针”,而是主键值,并以此作为指向行的“指针”。这样的策略减少了当出现行移动或者数据页分裂时二级索引的维护工作。使用主键当做指针会让二级索引占更多空间,但好处是InnoDB在移动行时无需更新二级索引中的这个指针。

sphinx 主索引和增量索引_索引_hash索引和btree索引

MyISAM表的数据分布

col1列上的索引

sphinx 主索引和增量索引_索引_hash索引和btree索引

col2列上的索引

实际上MyISAM中主键索引和其他索引在结构上没有什么不同。

从下图可以看出InnoDB和MyISAM保存数据和索引的区别。

hash索引和btree索引_索引_sphinx 主索引和增量索引

聚集索引的优点:

聚集索引的缺点:

顺序主键的策略:

在InnoDB表中使用自增主键是既简单性能又高的策略,这样可以保证数据按顺序写入。最好避免随机的聚集索引,从性能的角度考虑,使用UUID来作为聚集索引是很糟糕的,这样不仅插入行花费的时间长,而且索引占用的空间也更大。

———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: wxii2p22