MySQL 核心机制精讲:B+树查询、Buffer Pool、COUNT 优化与 CHAR/VARCHAR 实战指南

一、请详细描述一下MySQLB+树查询数据的过程

B+树查询数据分两个阶段: 1. 先从根节点往下定位到叶子节点。 2. 在叶子节点内部定位到具体的数据行。

  1. 第一阶段是树的垂直查找,从根节点开始,要查询的键值和节点内存储的索引的键值作比较,通过二分查找,来确定落在哪个区间,重复这个过程,直到找到根节点。一棵三层的B+树最多经过三次磁盘IO就可以定位到叶子节点。
  2. 第二阶段是页内查找,叶子节点也是一个16KB大小的数据页,一个叶子节点能存很多数据,InnoDB通过目录页来加速查找。目录页把记录分成了多个组,每个槽记录组内的最大数;通过对目录页的二分查找能定位到对应的组,组内是通过单向链表连接的,通过对单项链表遍历就能找到目标记录。

整个过程:根节点->中间节点->叶子节点->二分查找目录页->遍历单向链表

二、Buffer Pool的作用

缓存热点数据页

实际查询时不是每次都从磁盘中读,Buffer Pool会缓存热点数据页,所以实际的查询过程是:

  1. 先在Buffer Pool中查询,有就直接用,不用走磁盘
  2. 没有就从磁盘里读取到数据页并写进Buffer Pool

三、MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?

三者都是统计行数的聚合函数,核心区别是对于null处理不同

  1. count(*)count(1)会统计所有的行,包括null
  2. count(字段名)不会统计字段名内为null的行。

四、如果要统计一张 5000 万行的订单表有多少条记录,直接 count(*) 太慢,你怎么优化?

  1. 如果允许存在误差的话,可以直接SHOW TABLE STATUS拿估算值,毫秒级反应。
  2. 如果不允许出现误差,又要求快速响应,可以在Redis里维护一个计数器。要处理好缓存一致性问题,例如事务消息或定期校验

五、count(*) 走的是主键索引还是二级索引?

  • 如果有二级索引的话走的是二级索引,因为二级索引只存储索引列和主键,占用空间小,扫描的数据页少,IO开销更低。
  • 具体可以用explain去分析key命中的索引

六、MySQL中CHARVARCHER的区别是什么?

CHAR是定长的,VARCHAR是变长的

  1. CHAR(10)不管存几个字符,都占10个字符的空间,不够用空格填充。
  2. VARCHAR(10)存多少占多少,最后在花1-2个字节记录长度。

七、VARCHAR(N) 的 N 会影响排序性能

  • MySQL 执行 ORDER BY 时会用到 sort_buffer,如果要排序的数据放不下,就得走 双路排序:先把排序字段和主键放进 sort_buffer 排好序,再回表取完整数据。多了一次回表,性能差不少。
sql 复制代码
-- a、b、c 都是 VARCHAR(1000),即使实际数据很短
SELECT a, b, c FROM t1 WHERE a = '面试鸭' ORDER BY b;

-- MySQL 按每行 3000 字符算空间,sort_buffer 放不下就走双路排序

八、CHAR 读取时会自动去掉尾部空格

CHAR 存储时会用空格填充到定长,读取时 MySQL 会自动去掉尾部空格。这可能导致意想不到的问题:

sql 复制代码
CREATE TABLE t (c CHAR(5));
INSERT INTO t VALUES ('abc  ');  -- 故意存两个空格
SELECT CONCAT('[', c, ']') FROM t;
-- 结果是 [abc],尾部空格被去掉了

九、什么时候用 CHAR?

别看 CHAR 好像很鸡肋,在特定场景下还是有优势的:

1)存储固定长度的编码,比如 ISO 国家代码 CHAR(2)、MD5 摘要 CHAR(32)、UUID 去掉横杠后 CHAR(32)

2)存储单字符的状态标记,比如性别 CHAR(1) 存 M/F

3)频繁更新的短字段,CHAR 不会产生碎片,VARCHAR 长度变化可能导致页分裂

相关推荐
程序员夏洛4 分钟前
Redis 的持久化机制有哪些?
java·数据库·redis
l1t5 分钟前
DeepSeek总结的修复pgrust v0.2 #83:generate_series 聚合及其底层的两个成本 - #84
数据库·postgresql
厦门德仔1 小时前
【YiFeiWebApi】易飞ERP与WMS系统接口对接实战:从0到1全流程指南
大数据·数据库
内存漫游1 小时前
Page 到底是什么:数据库如何把一条条记录放进磁盘
数据库
小镇敲码人1 小时前
【深入浅出】之Qt 事件系统实战:鼠标、键盘、滚轮、窗口与定时器事件
数据库·qt·网络协议·mysql·http
Sirens.1 小时前
MySQL数据库:索引
数据库·mysql
2601_962072501 小时前
大数据-234 离线数仓 - 异构数据源 DataX 将数据 从 HDFS 到 MySQL
大数据·mysql·hdfs
treacle田1 小时前
达梦数据库-Linux DM主备集群动态增加节点-记录总结
linux·运维·数据库·达梦主备集群动态扩展
一只专注api接口开发的技术猿2 小时前
Open Claw 实战|快速搭建电商商品监控与数据分析能力
大数据·数据库·数据挖掘·数据分析
杨云龙UP2 小时前
Oracle 19c RMAN历史备份清理失败:CONTROL_FILE_RECORD_KEEP_TIME 问题排查与整改实战
linux·运维·网络·数据库·oracle·rac