当前位置: 首页 > backend >正文

MySQL问题4

MySQL中varchar和char的区别

在 MySQL 中,VARCHARCHAR 都是用于存储字符串类型的字段,但它们在存储方式、性能、适用场景等方面存在明显区别:


1. 存储方式

类型说明
CHAR(n)定长字符串,始终占用固定 n 个字符空间。不足的会自动在右侧补空格(存储时),查询时会自动去除补空格。
VARCHAR(n)变长字符串,只占用实际字符长度 + 1 或 2 个字节(记录长度信息)

举例:

CHAR(10): 存 'abc',存储为 'abc       '(右侧补7个空格)
VARCHAR(10): 存 'abc',只占 3 + 1 = 4 个字节

2. 性能对比

特性CHARVARCHAR
读取速度较快(定长,容易定位)略慢(需读取长度信息)
更新性能稳定(定长不易产生碎片)大量更新可能导致行迁移和碎片
空间占用多(始终固定长度)少(根据实际长度变化)

CHAR 读取更快,但除非数据长度始终一致,否则它占用空间较大。


3. 使用场景推荐

场景推荐类型
固定长度,如身份证号、邮编、MD5、UUIDCHAR
可变长度,如名字、地址、备注等VARCHAR

4. 其他注意事项

  • 最大长度限制

    • CHAR 最多 255 个字符。
    • VARCHAR 最多 65535 字节(注意字符集影响,如 utf8 每字符占 3 字节)。
  • 行格式限制

    • InnoDB 表中,如果 VARCHAR 太长,可能会被拆分存储到“溢出页”。

口诀:

「定长用 CHAR,变长用 VARCHAR;空间选 VARCHAR,速度选 CHAR。」


MySQL中count()、count(1)和count(字段名)的区别

在 MySQL 中,COUNT()COUNT(1)COUNT(字段名) 都是用于统计行数的聚合函数,但它们在统计逻辑、NULL 处理、性能优化等方面存在区别。

1 、三者区别

表达式含义是否统计 NULL 行典型用途
COUNT(*)统计所有行数(包括 NULL)表行数统计
COUNT(1)统计所有行数(包括 NULL),效果等同于 COUNT(*)和 COUNT(*) 一样
COUNT(字段名)统计字段值不为 NULL 的行数判断某列有多少有效值

示例:

假设有一张表 users

idnameage
1Alice15
2NULL25
3CharlieNULL
4NULLNULL
1. SELECT COUNT(*) FROM users;

返回 4,统计全部行。

2. SELECT COUNT(1) FROM users;

返回 4,和 COUNT(*) 一样,1只是个常量

3. SELECT COUNT(name) FROM users;

返回 2,因为只有两行 name 不是 NULL。

4. SELECT COUNT(age) FROM users;

返回 2,同样只统计非 NULL 的 age


2、性能区别

  • COUNT(*)最推荐使用的统计行数方式:

    • MySQL 优化器会做特别优化,不实际读取列,直接走统计信息。
  • COUNT(1) 理论上和 COUNT(*) 等价,区别不大,但没有 COUNT(*) 优化彻底。

  • COUNT(字段名) 性能较慢,因为需要判断字段是否为 NULL

用途推荐用法
统计表的总行数COUNT(*)
统计某列的非空数量COUNT(字段名)
代替 COUNT(*)(不推荐)COUNT(1)

区别:

  1. COUNT(*):最全、最快,连 NULL 也算。
  2. COUNT(1):等价于 COUNT(*),但没优化优势。
  3. COUNT(字段):只数非 NULL 的字段行。

MySQL的B+树中查询数据的全过程

假设我们有以下索引结构(id 是主键):

          [30 | 60]/    |    \[10 20] [40 50] [70 80 90] ← 叶子节点,存数据
  • 根节点 [30, 60]:索引 key,不存数据
  • 叶子节点:[10,20], [40,50], [70,80,90] 存储完整行数据(聚簇索引)
  • 每个节点就是一页(Page),约16KB

1、查询过程(以查询 id = 70 为例)

步骤一:从根节点开始搜索

  • 根节点 key 为 [30, 60]
  • 70 > 60 → 选择第三个子节点:[70, 80, 90]

步骤二:进入叶子节点

  • 叶子节点是 [70, 80, 90]
  • 在叶子节点内部做二分查找或顺序查找
  • 找到 id=70 对应的整行数据(聚簇索引)

查找完成!


2、全过程总结(图解)

           +-------------+|  30   60    |   ← 根节点 (非叶子)+-------------+/     |      \+----------+ +------+---------+|10 20 ... | |40 50 ...| 70 80 90 ← 叶子节点+----------+ +------+---------+
  • 查询 id=45

    • 根节点:[30,60] → 45 位于中间 → 走中间分支
    • 进入 [40,50] 节点 → 找到 45 或返回不存在

示例:B+树结构示意图

以一个主键索引为例(InnoDB 聚簇索引),建表如下:

CREATE TABLE users (id INT PRIMARY KEY,name VARCHAR(20)
);

假设表中数据如下(id 是主键):

id: 10, 20, 30, 40, 50, 60, 70, 80, 90

经过 B+ 树组织后,大概结构如下:

                             [40]/       \[10, 20, 30]       [50, 60, 70] --------> [80, 90](页1)              (页2)                    (页3)
  • [] 表示一个页(Page),每页约16KB,包含多个 key
  • 叶子节点之间通过链表相连(→),支持范围查找
  • 中间节点只存索引 key,不存数据
  • 叶子节点存完整行数据(id, name)

查询过程可视化:查找 id = 70

Step 1:从根节点开始
┌───────────────┐
│     [40]      │ ← 根节点(非叶子)
└───────────────┘│└── id > 40,向右走Step 2:进入右子树
┌────────────────────┐
│   [50, 60, 70]      │ ← 叶子节点,页2
└────────────────────┘Step 3:在页2中顺序查找找到了 id = 70,对应整行数据 name = 'Tom'

查询完成,最多访问两页内存/磁盘页。


范围查询过程:查找 id BETWEEN 60 AND 85

Step 1:从根节点 [40] 开始,id > 40 → 右子树Step 2:访问页2 [50, 60, 70] → 拿到 60, 70Step 3:顺着链表 → 页3 [80, 90] → 拿到 80,停止最终结果:60, 70, 80

特性可视化图中的体现
多路平衡根节点拆成多个范围,指向多个子页
快速查找每层只需一次判断(最多 2~4 层)
范围查找快叶子节点链表结构,顺着链表走
聚簇存储叶子节点含完整行,不用回表
http://www.xdnf.cn/news/20158.html

相关文章:

  • 阿里云服务器配置ssl-docker nginx
  • 企业数字安全双保险:终端安全与数据防泄漏如何构筑全方位防护体系
  • React Hooks useContext
  • AI API Tester体验:API测试工具如何高效生成接口测试用例、覆盖异常场景?
  • 【建图+dsf/最长上升子序列dp】【记录最优解路径】P2196 [NOIP 1996 提高组] 挖地雷
  • C++ 音视频开发常见面试题及答案汇总
  • 【软考架构】V模型、W模型、增量模型和螺旋模型
  • Oracle 10g → Oracle 19c 升级后问题解决方案(Pro*C 项目)
  • Redis 内存管理机制:深度解析与性能优化实践
  • 阿里云国际代理:阿里云的云数据库是什么?
  • 《基于stm32的智慧家居基础项目》
  • python使用transformer库推理
  • Leetcode—721. 账户合并【中等】
  • Mattermost教程:用Docker搭建自己的开源Slack替代品 (团队聊天)
  • PyTorch训练循环详解:深入理解forward()、backward()和optimizer.step()
  • 光伏项目无人机踏勘--如何使用无人机自动航线规划APP
  • VMware替代 | ZStack生产级跨版本热升级等七大要素降低TCO50%
  • HDFS存储农业大数据的秘密是什么?高级大豆数据分析与可视化系统架构设计思路
  • OpenLayers常用控件 -- 章节五:鹰眼地图控件教程
  • 修改上次提交的Git提交日志
  • CodePerfAI体验:AI代码性能分析工具如何高效排查性能瓶颈、优化SQL执行耗时?
  • 《sklearn机器学习——聚类性能指标》调整兰德指数、基于互信息(mutual information)的得分
  • Mysql中模糊匹配常被忽略的坑
  • Netty从0到1系列之Netty整体架构、入门程序
  • Python迭代协议完全指南:从基础到高并发系统实现
  • 投资储能项目能赚多少钱?小程序帮你测算
  • Unity2022.3.41的TargetSdk更新到APILevel 35问题
  • Fairness, bias, and ethics|公平,偏见与伦理
  • 【科研绘图系列】R语言绘制论文合集图
  • 高等数学知识补充:三角函数