
本专栏为150道MySQL大厂高频面试题讲解分析,这些面试题都是通过MySQL8.0官方文档和阿里巴巴官方手册还有一些大厂面试官提供的资料。 MySQL应用广泛,在多个开发语言中都处于重要地位,所以最好都要掌握MySQL的精华面试题,这也是面试官最喜欢问的,现在面试官在面试的时候更关心的是某个技术点的深度,所以专栏的内容也会从底层开始讲解,本专栏会一直不断的进行更新,欢迎大家一起交流学习。
索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快。排序查找和范围查找速度非常快。数据都是紧密相连,数据库可以从更少的数据块中提取数据,节省了大量的IO操作 。自增的ID列为主键。主键为不可更新。MyISAM不支持聚簇索引。每个MySQL的表只能有一个聚簇索引。非空的唯一索引列代替。如果没有这样的列,InnoDB会隐式的定义一个主键作为聚簇索引。主键应选择有序的id,不建议使用无序的id,比如UUID、MD5、HASH、字符串作为主键,无法保证数据的顺序增长。假设有一个用户表 users,包含 id(主键)、name 和 age 列:
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(100),
age INT
);默认情况下,id 列是聚簇索引。当你插入数据时,数据行会按照 id 的顺序存储在磁盘上。
INSERT INTO users (id, name, age) VALUES (1, 'Alice', 30);
INSERT INTO users (id, name, age) VALUES (2, 'Bob', 25);
INSERT INTO users (id, name, age) VALUES (3, 'Charlie', 35);SELECT * FROM users WHERE id = 2;这个查询会很快,因为数据行和索引在一起,只需要一次磁盘I/O操作。
在 users 表上创建一个非聚簇索引:
CREATE INDEX idx_age ON users(age);SELECT * FROM users WHERE age = 25;这个查询首先会在非聚簇索引 idx_age 中查找符合条件的索引键(age = 25),然后通过这些索引键对应的指针找到数据行。这通常需要两次磁盘I/O操作:一次是查找索引,一次是查找数据行。
聚簇索引,只能在搜索条件是主键值时才发挥作用,因为B+树中的数据都是按照主键进行排序的,如果我们想以别的列作为搜索条件,那么需要创建非聚簇索引。
例如,以c2列作为搜索条件,那么需要使用c2列创建一棵B+树,如下所示:

这个B+树与聚簇索引有几处不同:
页内的记录是按照从c2列的大小顺序排成一个单向链表 。
页和页之间也是根据页中记录的c2列的大小顺序排成一个双向链表 。
c2列+页号。
c2列+主键这两个列的值。
一张表可以有多个非聚簇索引:


当需要查找某个关键字时,查询操作从B+树的根节点开始。在根节点中,将目标关键字与节点中的关键字进行比较,以确定下一步的遍历方向(向左或向右)。
根据比较结果,查询操作继续向下遍历至相应的子节点。在每一层中,都重复进行关键字的比较和遍历方向的确定,直至到达叶子节点。
当查询操作到达叶子节点时,叶子节点中存储的是数据的地址或主键值。此时,需要按照关键字的顺序在叶子节点中进一步查找匹配的数据地址或主键值。
非聚簇索引的查找效率受到多个因素的影响,包括B+树的高度、节点中的关键字数量、磁盘I/O次数等。由于非聚簇索引需要额外的指针或地址来访问实际的数据文件,因此其查找效率通常比聚簇索引低。然而,在需要频繁访问非主键列的情况下,非聚簇索引仍然可以显著提高查询效率。
**例如:**根据c2列的值查找c2=4的记录,查找过程如下:
根页面44定位到页42(因为2 ≤ 4 < 9)c2列没有唯一性约束,所以c2=4的记录可能分布在多个数据页中,又因为 2 ≤ 4 ≤ 4,所以确定实际存储用户记录的页在页34和页35中。定位到具体的记录。只存储了c2和c1(主键)两个列,所以我们必须再根据主键值去聚簇索引中再查找一遍完整的用户记录。