美文网首页
mysql索引浅析

mysql索引浅析

作者: 码农150 | 来源:发表于2020-07-06 12:33 被阅读0次

MySQL 的索引长什么样子?索引到底是怎么加速查询的?

事实上,在你还没有执行 create index 语句的时候,MySQL 就已经创建索引了。

聚簇索引

执行建表语句:

CREATE TABLE `student` (

`id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL COMMENT '主键id',

`student_no` VARCHAR ( 64 ) COMMENT '学号',

`name` VARCHAR ( 64 ) COMMENT '学生姓名',

`age` INT COMMENT '学生年龄',

PRIMARY KEY ( `id` )) ENGINE = INNODB CHARSET = utf8mb4 COMMENT = '学生信息表';

插入 5 条数据:

INSERT INTO student ( student_no, NAME, age )

VALUES

( 101, "Alice", 18 ),

( 102, "Bob", 19 ),

( 104, "Brandt", 15 ),

( 105, "David", 19 ),

( 109, "David", 18 );

在插入的过程中,MySQL 会用你指定的主键,在这里是递增主键,维护起一棵 B+树,主键从 1 开始递增,插入五条,所以是 1 到 5:

索引树

从 1 到 5,一个一个插入,你会看到 B+树在插入的过程中是怎么维护它的几个特性的:

有序:左边节点比右边小

自平衡:左右两边数量趋于相等

节点分裂:节点在遇到元素数量超过节点容量时,是如何分裂成两个的,这个也是 MySQL 页分裂的原理

模拟工具只支持插入一个值,所以你看不到主键之外的其他数据,实际上,这棵 B+树的叶子节点是带有行的全部数据的:

完整树结构

如果没有这棵 B+树,你要根据主键查询,比如

select*fromstudentwhereid=5;

数据是无序的,你只能全表扫描

有同学会说主键不是递增的吗,那不就可以用二分法来查找?不是的,主键虽然是递增的,但是如果你写入磁盘时,没有去维护有序数组这样一个数据结构(比如你删掉了 4,怎么把 5 往前面挪),那数据在磁盘里依旧是无序的,查找时只能随机查找,而如果你维护了有序数组这样的数据结构,其实也是建了索引,只是建了不一样的数据结构的索引罢了。

现在有了这棵 B+树,数据被有规律的存储起来,查找id=5,也不再大浪淘沙,而是变得很有章法:

从上到下,先找到 3,5 比它大,找右节点

接着找到 4,发现 5 还是比它大,继续找右节点

这次到达叶子节点了,叶子节点是一个递增的数组,那就用二分法,找到 id=5 的数据

你要访问磁盘的次数,是由这棵树的层数决定的。为了方便说明,我在文章里举的例子的数据量不会太大,所以用不用索引,性能提升的效果不明显,但是你可以脑补下大数据量的画面。

如果你没有指定主键呢?没关系,唯一键也可以。

连唯一键也没有?也没关系,mysql会给你建一个rowid字段,用它来组织这棵 B+树.

反正 MySQL 就一个目的,数据要有规律的存储起来,数据是否被规律的管理起来,是数据库和文件系统区分开来的重要因素。

这个 MySQL 无论如何都会建起来,并且存储有完整行数据的索引,就叫聚簇索引(clustered index)。

二级索引

聚簇索引只能帮你加快主键查询,但是如果你想根据姓名查询呢?

对不起,看看上面这棵树你就知道,数据并没有按照姓名进行组织,所以,你还是只能全表扫描。

不想全表扫描,怎么办?那就给姓名字段也加个索引,让数据按照姓名有规律的进行组织:

create index idx_name onstudent(name);

这时候 MySQL 又会建一棵新的 B+树:

name索引树

你会发现这棵树的叶子节点,只有姓名和主键ID两个字段,没有行的完整数据,这时候你执行:

select*fromstudentwherename="David";

MySQL 到你刚刚创建的这棵 B+树 查询,快速查到有两条姓名是“David”的记录,并且拿到它们的主键,分别是 4 和 5,但是你要的是select *呀,怎么办?

别忘了,MySQL 在一开始就给你建了一棵 B+树 了,把这两棵树,放在一起,拿着从这棵树上查到的两个主键ID,去聚簇索引找,事情不就解决了?

查找过程

这个不带行数据完整信息的索引,就叫二级索引(secondary index),也叫辅助索引。

复合索引

继续,如果我还想根据姓名和年龄同时查询呢?

select*fromstudentwherename="David"and age=18;

还是那个道理,数据虽然按照 name 有规律的组织了,但是没有按照 age 有规律组织,所以我们要给name和age同时建索引:

create index idx_name_age onstudent(name,age);

这时候 MySQL 又会建一棵 B+树,这下 B+树 的节点里面,不只有 name,还有 age 了:

查询过程

注意观察我用红色虚线框出来的那两个节点,这是这棵树和上面那棵只给 name 建索引的树的唯一区别,两个元素换了个位,因为排序时,是先用 name 比较大小,如果 name 相同,则用 age 比较

还是那句话,这里举的例子数据量很少,你可以想象下有一万个叫“David”的学生,年龄随机分布在 13 到 20 之间,这时候如果没有按照 age 进行有规律的存储,你还是得扫描一万行数据。

只给 student 表建idx_name_age这个复合索引,这两个 sql 语句,会走索引吗?

select*fromstudentwherename="David";

select*fromstudentwhereage=18;

相关文章

  • 浅析Mysql索引

    应用场景 非常小的表:不建议使用索引,简单的全表扫描更高效 中到大型表:使用索引 特大型表:定位单条记录速度很慢且...

  • 浅析MySQL索引

    # 为什么要建立索引 > 多数情况下,不使用索引,试图通过其他途径来提高性能,纯粹是浪费时间(出自《MySQL技术...

  • mysql索引浅析

    说到索引,很多人都知道“索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址,在数据...

  • mysql索引浅析

    MySQL 的索引长什么样子?索引到底是怎么加速查询的? 事实上,在你还没有执行create index语句的时候...

  • mysql索引浅析

    关键字 mysql索引innodbB+树 mysql的innodb存储引擎是如何保存数据的 innodb引擎需要有...

  • MySQL索引及查询优化书目录

    MySQL索引的原理之索引目的 MySQL索引的原理之索引原理 MySQL索引的原理之索引的类型 MySQL索引的...

  • mysql索引优化浅析(1)

    近来接触到一些mysql优化的例子,也看了网上相关的一些文章,这里通过自己的实践来总结下近段时间的经验吧。为了以后...

  • MySQL InnoDB 索引结构浅析

    看图说话 聚集索引特点 B+树结构; 叶子节点存行记录数据,叶子节点初始化一页(磁盘管理单位),当一页达到装载因子...

  • 高性能的索引策略

    MySQL查询基础-查询执行过程 MySQL聚簇索引 MySQL覆盖索引 MySQL索引扫描排序 MySQL冗余和...

  • MySQL索引的使用

    MySQL索引 MySQL索引可以快速提高MySQL的检索速度。索引分单列索引和组合索引单列索引:即一个索引只包含...

网友评论

      本文标题:mysql索引浅析

      本文链接:https://www.haomeiwen.com/subject/hmvjqktx.html