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 长度变化可能导致页分裂

相关推荐
广州灵眸科技有限公司6 小时前
xfce桌面触摸校准:基于灵眸科技EASY-EAl-Orin-Nano
数据库·windows·科技
Cloud云卷云舒8 小时前
云卷云舒:从Oracle/MySQL迁移到HaishanDB:迁移评估工具核心技术拆解
mysql·oracle·ai-native·haishandb·信创数据库替换
憧憬成为web高手9 小时前
皮卡丘靶场速通--sql 2
数据库·sql·mybatis
段一凡-华北理工大学9 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
oradh11 小时前
Oracle XTTS实现跨版本迁移和升级(Oracle 11g单库升级至19C RAC集群)
数据库·oracle·11g升级19c·xtts跨版本迁移和升级
用户713335851562411 小时前
MySQL - 事务、redo/undo 日志与 MVCC
mysql
z1234567898612 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
程序猿DD12 小时前
一个 API Key,统一调用大模型、生图和联网搜索
数据库·网关
java_logo12 小时前
Docker Compose 部署 ClickHouse:快速搭建高性能列式数据库
数据库·clickhouse·docker·列式数据库·轩辕镜像·高性能数据库·clickhouse部署教程
用户713335851562412 小时前
MySQL - InnoDB 的 Buffer Pool
mysql