2025-01-15🌱上海: ☀️ 🌡️+4°C 🌬️↓19km/h
# 请详细描述 MySQL 的 B + 树中查询数据的全过程
# MySQL 中 count(*)、count(1)和 count(字段名)有什么区别?
# 简要回答
都是用来统计行数的聚合函数,但是还有一些区别:
-
功能上:
-
1. count (*) 会统计表中所有行的数量,包括 null 值(不会忽略任何一行的数据)。由于只是计算行数,不需要对具体的列进行计算,所以性能一般较高
-
2. count(1)和 count(*)几乎没有差别,也会统计表中包括 null 值的所有行的数量
-
3. count(字段名)只统计指定字段不为 null 的行数。
-
效率上:
-
1. count(1)和 count(*)效率一致(官网上声明了)
-
2. count(字段)查询就是全表扫描,正常情况下还需要判断字段是否是 null 值,所以理论上会比其他两个慢。但是如果字段不为 null,比如是主键,那么理论上也差不多。效率上不需要纠结,主要看使用场景是否需要统计 null 值
# 扩展知识
MyISAM 中,由于只有表锁,因此把每张表的总数单独记录维护(表锁使得对表的修改是串行,因此能维护总数,毕竟查询的时候不会有别人修改记录数据导致查询的总数不一致)所以 count(*)非常快,等于直接返回了一个字段,前提是不需要条件过滤而是直接返回整表数据。
InnoDB 中由于支持行锁,所以会有很多并发修改表的数据,因此无法维护记录的总数,但相应的 innoDB 也对 count(*)和 count(1)也做了一定的优化。
count 需要扫描全表。如果扫的是主键索引,因为主键索引的叶子节点上保存的是完整的记录,占据的空间和内存都比较大,此时选择二级索引扫描成本会耕地。
在没有对应的条件过滤等功能时 innoDB 会评估这个成本选择合适的索引扫描。
# MySQL 中 varchar 和 char 有什么区别?
# 简要回答
特点 | char | varchar |
---|---|---|
存储方式 | 定长字符串(字符串长度小于定义的长度,会使用空格进行填充) | 变长字符串(不会额外填充空格) |
存储空间 | 始终占用固定长度空间 | 只占用实际需要的存储空间 |
性能影响 | 始终占用固定长度的存储空间,因此在存储时可能会浪费一些空间 <br>(不需要记录额外长度信息,在某些情况下可能更快) | 只占用实际需要的存储空间,因此可以节省存储空间 <br>(需要记录额外长度信息,占据 1~2 个字节),在某些情况下可能稍微影响性能) |
适用场景 | 适合存储固定且短的字符串 | 适合存储变化或较长的字符串 |