今天是新年,祝大家新年快乐,但是生活还是得继续。
后面也会持续更新,学到新东西会在其中补充。
建议按顺序食用,欢迎批评或者交流!
缺什么东西欢迎评论!我都会及时修改的!
大部分截图和文章采用该书,谢谢这位大佬的文章,在这里真的很感谢让迷茫的我找到了很好的学习文章。我只是加上了自己的拙见。我只是记录学习没有任何抄袭意思
MySQL 是怎样运行的:从根儿上理解 MySQL - 小孩子4919 - 掘金小册
MySQL Server
有一个称为查询优化器的模块,一条查询语句进行语法解析之后就会被交给查询优化器来进行优化,优化的结果就是生成一个所谓的执行计划,这个执行计划表明了应该使用哪些索引进行查询,表之间的连接顺序是啥样的,最后会按照执行计划中的步骤调用存储引擎提供的方法来真正的执行查询,并将查询结果返回给用户。
CREATE TABLE single_table (
id INT NOT NULL AUTO_INCREMENT,
key1 VARCHAR(100),
key2 INT,
key3 VARCHAR(100),
key_part1 VARCHAR(100),
key_part2 VARCHAR(100),
key_part3 VARCHAR(100),
common_field VARCHAR(100),
PRIMARY KEY (id),
KEY idx_key1 (key1),
UNIQUE KEY idx_key2 (key2),
KEY idx_key3 (key3),
KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;
为这个single_table
表建立了1
个聚簇索引和4
个二级索引,分别是:
-
为
id列
建立的聚簇索引。 -
为
key1列
建立的idx_key1
二级索引。 -
为
key2列
建立的idx_key2
二级索引,而且该索引是唯一二级索引。 -
为
key3列
建立的idx_key3
二级索引。 -
为
key_part1、key_part2、key_part3
列建立的idx_key_part二级索引
,这也是一个联合索引。
#借用评论区一位大佬写的存储过程
DELIMITER //
CREATE PROCEDURE InsertRecords()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= 10000 DO
INSERT INTO single_table (key1, key2, key3, key_part1, key_part2, key_part3, common_field) VALUES
(CONCAT('Key1_', i), i, CONCAT('Key3_', i), CONCAT('Part1_', i), CONCAT('Part2_', i), CONCAT('Part3_', i), 'CommonField');
SET i = i + 1;
END WHILE;
END //
DELIMITER ;
CALL InsertRecords();
访问方法(access method
)的概念
查询的执行方式大致分为下边两种:
- 使用全表扫描进行查询
把表的每一行记录都扫一遍,把符合搜索条件的记录加入到结果集就完了。 - 使用索引进行查询
因为直接使用全表扫描的方式执行查询要遍历好多记录,所以代价可能太大了。
如果查询语句中的搜索条件可以使用到某个索引,那直接使用索引来执行查询可能会加快查询执行的时间。- 针对主键或唯一二级索引的等值查询
- 针对普通二级索引的等值查询
- 针对索引列的范围查询
- 直接扫描整个索引
MySQL
执行查询语句的方式称之为访问方法或者访问类型。
const
SELECT * FROM single_table WHERE id = 1438;
MySQL
会直接利用主键值在聚簇索引中定位对应的用户记录
对于single_table
表的聚簇索引就是id列
。
B+树
叶子节点中的记录是按照索引列排序的,对于聚簇索引来说,它对应的B+树
叶子节点中的记录就是按照id列
排序的。
唯一二级索引列来定位一条记录的速度也是很快的。注意这里是唯一的
SELECT * FROM single_table WHERE key2 = 3841;
第一步:先从idx_key2
对应的B+树
索引中根据key2
列与常数的等值比较条件定位到一条二级索引记录
第二步:再根据该记录的id值
到聚簇索引中获取到完整的用户记录。
通过主键或者唯一二级索引列与常数的等值比较来定位一条记录是像坐火箭一样快的,所以把这种通过主键或者唯一二级索引列来定位一条记录的访问方法定义为:const
,意思是常数级别的,代价是可以忽略不计的。
不过这种const
访问方法只能在主键列或者唯一二级索引列和一个常数进行等值比较时才有效,如果主键或者唯一二级索引是由多个列构成的话,索引中的每一个列都需要与常数进行等值比较,这个const
访问方法才有效(这是因为只有该索引中全部列都采用等值比较才可以定位唯一的一条记录)。
对于唯一二级索引来说,查询该列为NULL值
的情况比较特殊,比如这样:
SELECT * FROM single_table WHERE key2 IS NULL;
唯一二级索引列并不限制 NULL 值
的数量,所以上述语句可能访问到多条记录,也就是说 上边这个语句不可以使用const
访问方法来执行。
ref
对某个普通的二级索引列与常数进行等值比较
SELECT * FROM single_table WHERE key1 = 'abc';
对于这个查询,我们当然可以选择全表扫描