这篇文章上次修改于 1751 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

Mysql 数据库的基本组成部分

数据库基本组成

  1. 当我们使用 Mysql 查询时,首先客户端要与数据库建立一个连接。
  2. 连接器的责任是来管理连接,以及各项权限验证。因为连接特别重,所以通过连接器来管理连接的连接、释放、超时断开。
  3. 然后 SQL 语句来到查询缓存(QueryCache),如果该语句是查询语句并且可以命中缓存则直接返回数据。如果是更新或删除语句,则删除对应表的查询缓存。查询缓存是 KV 形式的内存缓存。
  4. 如果没有缓存则来到语法分析器,来验证和分析语法,验证查询的表和列是否正确。
  5. 经过语法分析器 Mysql 知道了你要干什么,优化器就可以选择使用索引等它认为最快的执行方案来执行。
  6. 进过分析器后,执行器则再次检查表权限,随后调度表相应的存储引擎去执行语句,返回数据到数据库服务层。
  7. 通过数据库引擎查询的数据返回到数据库服务层再根据语句进行操作(比如过滤查找等等操作),然后返回数据。

索引

我们这里说的索引是 Mysql 默认的存储引擎 InnoDB 的索引方式。InnoDB 会有一个默认索引「主键索引」,所有数据都是根据 ID 主键组织成的一颗 B+ 树,也就是说所有数据都是存储在 B+ 树上的。

B+ 树基本结构.png

我们数据的存储结构就如上图,这是我们主键索引的样子,但是非主键索引在结构上都是相仿的。

  1. B+ 树像一棵二叉树,但是不同的是 B+ 树每个子叶子结点上想一个链表,有很多数据。
  2. 中间节点只有索引数据,而没有其他数据。只有最底层的叶子节点才有数据。
  3. 我举得例子的每个叶子节点最多只有两个数据,实际上 Mysql 每个叶子结点是有很多数据的。那么这个最大数量有没有一个具体的值,有的,大概是磁盘的一页,一页是多大呢?操作系统,文件系统不一样页的大小都不太一样。但通常是 4KB。也就是 最大数量 = 4KB / 每条数据占空间大小。
  4. 为什么每个叶子结点都有很多数据呢?因为数据是存储在磁盘上的,而内存要比磁盘快的多的多,所以每次读取磁盘都读取一块数据放到内存处理,这样是最有效率的,所以才选择这样的一个策略。
  5. 这也是为什么让我们不要滥用索引,因为每建一个索引都会产生这样的一棵树,再插入数据时他要调整每一颗树,都调整完了才算插入成功。所以如果索引过多就会造成插入变得很慢。

至于 B+ 树的具体特性,我会另外写一篇文章来解释。

查询过程

那我们查询的时候是怎么使用索引的呢?
如果你根据 ID 查询,比如 select * from T where id = 1024; 他会通过 B+ 树来迅速定位到相关数据附近的位置后再查询,然后返回数据,这个速度会非常的快。
如果你想根据名字查询(名字非主键),比如 select * from T where name = '张三' and sex = '男'; 因为没有索引,他只能去从第一条数据开始,一条一条的比对。所以数据就会很慢。

联合索引详情.png

简单展示一下,联合索引的 B+ 树大概什么样子。

如果建立了索引他就会根据索引进行查询,查询到主键 ID 了之后,再根据 ID 去查询表里其他的字段(这个过程叫做回表,划重点记住「回表」)。这样做会比我们逐条对比更加有效率。

如果的语句是 select id,name,sex from T where name = '张三' and sex = '男'; ,如果使用上述联合索引那么他的查询会更快,因为他不需要查询其他数据,所以就没有了回表这个过程。

但是有一点需要注意,我上边演示的是 (name,sex) 的联合索引,我们查询 select * rom T where name = '张三' and sex = '男';select * from T where name = '张三'; 都能使用该索引,但是 select * from T where sex = '男'; 却无法使用该联合索引,联合索引查询时一定要包含最左边的查询条件,否则该查询无法使用该联合索引。

另外联合索引的排序规则是左优先的,右边的优先级较低,所以我们建立联合索引一定要把常用的字段往左排。

总结

讲到这里希望大家在遇到 Sql 语句执行的时候心里有个大概的过程,出现问题或执行缓慢可以在脑海中还原他的执行过程找到问题的原因所在。