MySQL 如何处理 NULL 值,对性能有什么影响?
# 1. MySQL 对 NULL 值的处理规则
NULL 是 MySQL 中表示 “未知值” 的特殊标记(不同于空字符串''、0),处理规则如下:
- 比较运算:NULL 与任何值比较(=、!=、>、<)结果均为 NULL(非 TRUE/FALSE),需用
IS NULL/IS NOT NULL判断;- 示例:
WHERE age = NULL(无结果),正确写法WHERE age IS NULL;
- 示例:
- 聚合函数:聚合函数(COUNT、SUM、AVG)会忽略 NULL 值;
- 示例:
COUNT(age)(忽略 age 为 NULL 的行),COUNT(*)(不忽略 NULL 行,统计所有行);
- 示例:
- 索引处理:B-Tree 索引(InnoDB 默认索引)支持存储 NULL 值,但 NULL 值会被当作一个特殊值存储在索引树的最左侧(MySQL 8.0 后可配置排序);
- 唯一索引:唯一索引允许存储多个 NULL 值(因 NULL≠NULL,不违反唯一性约束);
- 字符串处理:NULL 与字符串拼接(
CONCAT('a', NULL))结果为 NULL,需用IFNULL处理(CONCAT('a', IFNULL(col, '')))。
# 2. NULL 值对性能的影响
- 1. 索引效率下降:
- NULL 值会增加索引树的复杂度(需单独存储 NULL 值节点),导致索引扫描行数增加;
- 使用
IS NULL/IS NOT NULL查询时,索引可能失效(如WHERE age IS NULL,若 age 字段 NULL 值较多,MySQL 可能选择全表扫描);
- 2. 排序与分组性能差:
- 排序时,NULL 值会被排在最前或最后(取决于排序方向),增加排序开销;
- 分组时,所有 NULL 值会被分为一组,但分组效率低于非 NULL 值;
- 3. 聚合函数计算额外开销:
- 聚合函数(如 SUM、AVG)需先判断值是否为 NULL,再进行计算,比处理非 NULL 值多一步操作;
- 4. 存储开销增加:
- 部分数据类型存储 NULL 值需额外空间(如 VARCHAR 存储 NULL 时,需存储长度标识为 NULL);
- 复合索引中,NULL 值会导致索引过滤性下降(如
idx_age_name (age, name),age 为 NULL 时,name 字段无法使用索引)。
# 3. 优化建议:避免 NULL 值
- 1. 字段设置为 NOT NULL:为字段设置默认值(如
age INT NOT NULL DEFAULT 0、name VARCHAR(20) NOT NULL DEFAULT ''),用默认值替代 NULL; - 2. 用特殊值表示 NULL 含义:如状态字段用
-1表示 “未知”,时间字段用'1970-01-01'表示 “未设置”,避免使用 NULL; - 3. 查询时避免 IS NULL/IS NOT NULL:用默认值替代 NULL 后,查询条件改为
WHERE age = 0(替代age IS NULL)、WHERE age != 0(替代age IS NOT NULL),确保索引有效; - 4. 索引设计优化:若字段必须存储 NULL 值,避免将其作为联合索引的前导字段(如
idx_name_age (name, age),name 非 NULL,age 可 NULL),提升索引过滤性。
上次更新: 12/30/2025