加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_宿迁站长网 (https://www.0527zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

图解 MySQL 索引,写得实在太好了!

发布时间:2022-10-18 21:01:21 所属栏目:MySql教程 来源:网络
导读:
从上面图可知B+树的叶子节点存放了所有的索引值,并且叶子结点之间以链表的形式相互关联,所以我们只需从最左的链表遍历的话即可查找所有的值,最常见的用途就是范围查找,而B树则不满足这

mysql删除所有索引_mysql 删除索引 很慢_MySQL 索引

从上面图可知B+树的叶子节点存放了所有的索引值,并且叶子结点之间以链表的形式相互关联,所以我们只需从最左的链表遍历的话即可查找所有的值,最常见的用途就是范围查找,而B树则不满足这范围查找,又或者说实现特别复杂,所以Mysql最终选择了使用B+树实现这一功能。

1.1 B-Tree 索引(B+树)

先说明一下,虽然叫在Mysql官方叫做B-Tree索引,但采用的是B+树数据结构。

B-tree索引能够加快访问数据的速度,不需要进行全表扫描,而是从索引树的根节点层层往下搜索,在根节点存放了索引值和指向下一个节点的指针。

下面看下单列索引的数据怎么组织的。

create?table?User(
`name`?varchar(50)?not?null,
`uid`?int(4)?not?null,
`gender`?int(2)?not?null,
?key(`uid`)
);

上面User 表给uid列创建了一个索引,那么往表里插入uid(96~102)的时候存储引擎是怎么管理索引的呢?看下面的索引树

MySQL 索引_mysql 删除索引 很慢_mysql删除所有索引

1.在叶子节点存放所有的索引值,非叶子节点值是为了更快定位包含目标值的叶子节点

2.叶子节点的值是有序的

3.叶子节点之间以链表形式关联

下面在看一下多列(联合)索引的数据怎么组织的。

create?table?User(
`name`?varchar(50)?not?null,
`uid`?int(4)?not?null,
`gender`?int(2)?not?null,
?key(`uid`,`name`)
);

给User 表创建了联合索引 key(uid,name) 这种情况下他的索引树是如下图所示。

mysql删除所有索引_mysql 删除索引 很慢_MySQL 索引

特点跟单列索引一样,不同之处在于他的排序,如果第一个字段相同时会按第二个索引字段排序。

如何通过B-tree快速查找数据?

mysql删除所有索引_mysql 删除索引 很慢_MySQL 索引

对于InnoDb 存储引擎的B-tree索引,会按一下步骤通过索引找到行数据

对于MyISAM 存储引擎的B-tree索引,会按一下步骤通过索引找到行数据

1.2 Hash 索引(哈希表)

哈希索引是基于哈希表来实现的,只有精确匹配所有的所有列才能生效。另外,推荐大家关注下公众号Java技术栈回复mysql可以获取系列mysql教程。

也就是说假设有个hash索引 key (col1,col2) 那么每次只有 col1和col2两个字段都用才能够生效。因为生成hash索引的时候是根据一个hash函数对所有的索引列取hash值来实现的。

如下方图,有个hash索引key(name)

mysql删除所有索引_MySQL 索引_mysql 删除索引 很慢

当我们执行 mysql> select * from User where; 时怎么利用hash索引快速查找的?

第一步,计算出hash值,hash(张三) = 1287

第二步,定位行号,比如key=1287 对应的行号为3

第三步MySQL 索引,找到指定行并且比较name列值是否为张三做个校验

mysql 删除索引 很慢_MySQL 索引_mysql删除所有索引

2.常见索引种类(应用层面)

主键索引

create?table?User(
`name`?varchar(50)?not?null,
`uid`?int(4)?not?null,
`gender`?int(2)?not?null,
?primary?key(`uid`)
);

主键索引是唯一的,通常以表的ID设置为主键索引,一个表只能有一个主键索引,这是他跟唯一索引的区别。

唯一索引

create?table?User(
`name`?varchar(50)?not?null,
`uid`?int(4)?not?null,
`gender`?int(2)?not?null,
?unique?key(`name`)
);

唯一索引主要用于业务上的唯一约束,他跟主键索引的区别是,一个表可以有多个唯一索引。

单列索引

create?table?User(
`name`?varchar(50)?not?null,
`uid`?int(4)?not?null,
`gender`?int(2)?not?null,
?key(`name`)
);

以某一个字段为索引

联合索引

create?table?User(
`name`?varchar(50)?not?null,
`uid`?int(4)?not?null,
`gender`?int(2)?not?null,
?key(`name`,`uid`)
);

两个或两个以上字段联合组成一个索引。

还有其他不常用的就不介绍了~

3.聚簇索引与非聚簇索引

什么是聚簇索引?

聚簇索引指的是他的 索引和行数据 在一起存储。也就是在一颗B+树的叶子结点上存储的不仅是他的索引值,还有对应的某一行的数据。待会儿看图便知。

聚簇索引不是一种索引,而是一种数据存储组织方式 !!!

crreate?table?test(
??col1?int?not?null,
??col2?int?not?null,
??PRIMARY?KEY(col1),
??KEY(col2)
);

MySQL 索引_mysql 删除索引 很慢_mysql删除所有索引

可以看出叶子结点除了存储索引值 列col1 (3994700)值 之外还存储了其他列的值,如列col2 (92813),如果还有别的列的话也会存储,或者换句话说聚簇索引树 在叶子节点上存储某个索引值对应的一行数据。

下图是非聚簇索引(二级索引)的数据组织方式。

索引列是 col2

MySQL 索引_mysql 删除索引 很慢_mysql删除所有索引

与聚簇索引不同的是非聚簇索引在索引树叶子节点上除了索引值之外只存了主键值。而聚簇索引则存了一行数据。

假如有一条sql 语句 select * from test where col2=93;

上面这条语句会经历两次从索引树查找过程

1.第一步从非聚簇索引的索引树上找到包含col2=93的叶子节点,并定位到行的主键 3

2.第二步 根据主键 3 在从聚簇索引定位包含 主键=3的叶子节点并返回全部行数据。

以上说的都是基于InnoDb存储引擎的,MyISAM是不支持聚簇索引的,因为他的数据文件和索引文件是相互独立存储的 MyISAM存储引擎的索引树的叶子节点不会寸主键值,而存一个指向对应行的地址或者说是指针,然后再从表数据文件里去找,如下面图所示。

mysql删除所有索引_MySQL 索引_mysql 删除索引 很慢

结论:

4.覆盖索引

覆盖索引就是指索引包含了所有需要查询的字段。

create?table?User(
`name`?varchar(50)?not?null,
`uid`?int(4)?not?null,
`gender`?int(2)?not?null,
?key(`uid`,`name`)
);

假如表 User有三个字段 User (name,uid,gender),且有个联合索引 key(name,uid)那么执行如下面这条sql查询时就用到了 覆盖索引。

select name,uid from User where name in ('a','b') and uid >= 98 and uid

(编辑:云计算网_宿迁站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!