SQL原理| 青训营笔记

188 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天
程序中对于 DB 的应用逻辑如图: |600 整个 DB 部分可以理解为两个部分: Server层存储引擎

  1. Server层 负责建立连接、分析和执行 SQL .涉及大多数核心模块.

连接器,查询缓存、解析器、预处理器、优化器、执行器、内置函数、跨存储引擎过程

  1. 存储引擎 负责数据的存储和提取。

InnoDB、MyISAM、Memory 等. 索引数据结构实现. 从 MySQL 5.5 版本开始, InnoDB 成为了 MySQL 的默认存储引擎.

Server 层

连接器

Linux 链接 MySQL:

# -h 指定 MySQL 服务得 IP 地址,如果是连接本地的 MySQL服务,可以不用这个参数;
# -u 指定用户名,管理员角色名为 root;
# -p 指定密码,如果命令行中不填写密码(为了密码安全,建议不要在命令行写密码),就需要在交互对话里面输入密码
mysql -h$ip -u$user -p
# 常用
mysql -uroot -p 

MySQL 采用 TCP 链接,先经过 TCP 三次握手

MySQL 的链接特点

  • 链接有 长链接短链接,长的少建立连接和断开连接的过程, 推荐长链接, 但是占用内存
  • 最大连接数由 max_connections 参数控制, 默认100
  • 目前链接数可 show processlist 查看, Sleep 表示空闲的连接
  • 最大空闲时由 wait_timeout 控制,默认值是 8 小时(28880秒)

查询缓存

SQL 是查询语句(select 语句),MySQL 就会先去查询缓存( Query Cache )里查找缓存数据.

鸡肋.只要更新就删除 MySQL 8.0 版本直接将查询缓存删掉了, MySQL 8.0 之前的版本 query_cache_type 设置成 DEMAND 可关闭

解析 SQL

执行 SQL

  • prepare 阶段,也就是预处理阶段;
    • 检查 SQL 查询语句中的表或者字段是否存在
    • 将 select * 中的 * 符号,扩展为表上的所有列;
  • optimize 阶段,也就是优化阶段;
    • 确定 SQL 执行方案: 根据查询成本
  • execute 阶段,也就是执行阶段;
    • 执行器存储引擎交互

三种方式执行过程:

1.主键索引查询
select * from product where id = 1;

主键索引 + 等值查询

  1. 第一次查询调用 read_first_record 函数指针指向的函数,让存储引擎定位符合条件的第一条记录
  2. 记录是不存在的,就会向执行器上报记录找不到的错误,然后查询结束。如果记录是存在的,就会将记录返回给执行器;
  3. 执行器查询的过程是一个 while 循环,所以还会再查一次,但是这次因为不是第一次查询了,所以会调用 read_record 函数指针指向的函数,永远返回 - 1,退出循环
2 . 全表扫描
select * from product where name = 'iphone';

没有用到索引

  1. 执行器第一次查询,会调用 read_first_record 函数指针指向的函数,因为优化器选择的访问类型为 all,这个函数指针被指向为 InnoDB 引擎全扫描的接口,让存储引擎读取表中的第一条记录
  2. Server 层每从存储引擎读到一条记录就会发送给客户端,客户端是等查询语句查询完成后,才会显示出所有的记录
  3. 执行器查询的过程是一个 while 循环,所以还会再查一次,但是这次因为不是第一次查询了,所以会调用 read_record 函数,优化器选择的访问类型为 all,read_record 函数指针指向的还是 InnoDB 引擎全扫描的接口,所以接着向存储引擎层要求继续读刚才那条记录的下一条记录
  4. 直到存储引擎把表中的所有记录读完,退出循环,停止查询.
3. 索引下推
select * from t_user  where age > 20 and reward = 100000;

联合索引(age,reward)

  1. MySQL<5.6 : 每查询到一条二级索引记录,都要进行回表操作
    1. Server 层调用存储引擎的接口定位到 age > 20(第一个条件) 的第一条记录
    2. 根据二级索引的 B+ 树获取主键值,进行回表操作
    3. 判断该记录的 reward 是否等于 100000 (第二个条件)
    4. 循环,继续向存储引擎索要下一条记录
  2. MySQL>=5.6:索引下推
    1. Server 层调用存储引擎的接口定位到 age > 20(第一个条件) 的第一条记录
    2. 根据二级索引的 B+ 树,判断一下该索引中 reward 是否等于 100000(第二个条件):成立才回表
    3. 判断其他的查询条件(如果有)是否成立
    4. 循环,继续向存储引擎索要下一条记录

虽然 reward 列无法使用到联合索引 (最左匹配原则),但是可以索引下推