mysql字段设置为null的问题解决

 更新时间:2026年07月21日 09:33:15   作者:Ethan0107  
MySQL允许NULL的字段也能正常使用索引,但统计查询有大坑,本文用最直白的语言,带你避开COUNT、NOTIN和分组统计中的致命陷阱,感兴趣的可以了解一下

这个问题非常经典,直接给你结论:

MySQL 中,字段允许为 NULL,索引依然可以正常使用,但在统计、查询、存储和性能上有几个非常重要的“坑”需要注意。

我用最直白的方式给你讲清楚。

1. 索引是否会失效?—— 不会

只要查询条件写对了,索引就能用。

-- 表 t,字段 name 允许 NULL,name 上有索引

SELECT * FROM t WHERE name = '张三';  -- ✅ 可以用索引
SELECT * FROM t WHERE name IS NULL;   -- ✅ 也可以用索引(这个很多人误以为不行)

关键点:IS NULL 在索引中是有记录的,MySQL 会把 NULL 值也存进索引里(放在最前面或最后面,取决于引擎和排序方式)。

2. 最大的坑:COUNT、DISTINCT、分组统计会失真

这是最容易踩的坑,因为 NULL 在聚合函数里会被忽略。

操作结果原因
COUNT(name)只统计 非 NULL 的行数NULL 不算
COUNT(*)统计所有行不受 NULL 影响
SUM(age)忽略 NULL 值NULL 不参与计算
AVG(age)只算非 NULL 的平均值分母不包含 NULL 的行
DISTINCT name会把 NULL 当作一个独立值多个 NULL 只算一个

示例

-- 表里有 10 行,其中 3 行的 name 是 NULL
SELECT COUNT(name) FROM t;   -- 结果是 7,不是 10 ❗
SELECT COUNT(*) FROM t;      -- 结果是 10 ✅

教训:如果你想要统计所有行,用 COUNT(*) 或 COUNT(主键),别用 COUNT(可为 NULL 的字段)。

3. 索引存储和性能影响

① 索引大小会变大

  • 每个 NULL 值在索引中也需要占用存储空间(通常 1 个字节标记是否为 NULL)。
  • 如果字段允许 NULL,索引记录会多一个 NULL 标志位,导致索引稍微变大。

② 查询效率略微下降

  • 因为索引中多了一个“是否为 NULL”的判断逻辑。
  • 实际影响微乎其微,除非表非常巨大(几亿行),否则感觉不到。

③ 排序时 NULL 的位置

  • InnoDB 中,NULL 在索引中默认排在最前面(等价于最小值)。
  • MyISAM 中,NULL 默认排在最后面
  • 这会影响 ORDER BY 的结果顺序。

4. 组合索引中的 NULL 表现(很重要)

假设有组合索引 (a, b),两个字段都允许 NULL:

-- 数据:
(1, 1)
(1, NULL)
(NULL, 2)
(NULL, NULL)

索引能查到什么?

查询是否走索引说明
WHERE a = 1✅ 走索引正常
WHERE a IS NULL✅ 走索引NULL 在索引中有记录
WHERE a = 1 AND b IS NULL✅ 走索引组合索引完全匹配
WHERE b = 2❌ 不走索引因为 b 是组合索引的第二列,不能跳过 a 单独查 b

核心:组合索引中,NULL 值也参与索引构建,但最左前缀原则依然生效,不受 NULL 影响。

5. 一个容易被忽略的坑:NOT IN 和 NULL

SELECT * FROM t WHERE name NOT IN ('张三', '李四');

如果 name 允许 NULL,这个查询会漏掉 name = NULL 的行!

原因:NULL 和任何值比较都是 UNKNOWN(既不是 TRUE 也不是 FALSE),所以 NOT IN 会排除掉所有含 NULL 的行。

正确做法:

SELECT * FROM t WHERE name NOT IN ('张三', '李四') OR name IS NULL;

6. 总结一张表(记住要点)

问题结论
允许 NULL 的字段能建索引吗?✅ 可以
IS NULL 能走索引吗?✅ 可以
索引中 NULL 占空间吗?✅ 占,略大一点
COUNT(字段) 会统计 NULL 吗?❌ 不会,只统计非 NULL
NOT IN 会包含 NULL 吗?❌ 不会,需要额外加 OR IS NULL
唯一索引允许多个 NULL 吗?✅ 允许,多个 NULL 不冲突(因为 NULL != NULL)

7. 最佳实践建议

能设置 NOT NULL + 默认值,就尽量别允许 NULL。

原因:

  1. 避免统计失真(COUNT、AVG 等)。
  2. 避免查询条件中漏掉数据(NOT IN 等)。
  3. 索引存储更小,性能略好。
  4. 应用层不用处理 null 判空逻辑,代码更干净。

如果业务上确实需要表示“未知/无值”,那允许 NULL 也可以,但写 SQL 时一定要留意上述坑。

到此这篇关于mysql字段设置为null的问题解决的文章就介绍到这了,更多相关mysql字段为null内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL中root用户密码管理的三种场景完全指南

    MySQL中root用户密码管理的三种场景完全指南

    在MySQL数据库的日常运维中,root用户密码管理是最基础也最重要的操作之一,本文将针对三种常见场景,分别给出详细的操作步骤,涵盖MySQL 5.6、5.7、8.0三个主流版本,感兴趣的小伙伴可以了解下
    2026-02-02
  • mysql distinct去重,IFNULL空值处理方式

    mysql distinct去重,IFNULL空值处理方式

    文章介绍了如何在MySQL中使用`DISTINCT`命令去重和使用`IFNULL`函数处理空值,首先,通过Navicat新建数据库并准备数据,然后展示了如何使用`DISTINCT`命令去除重复数据和使用`IFNULL`函数将空值替换为“暂无”
    2025-01-01
  • Centos7 安装mysql 8.0.13(rpm)的教程详解

    Centos7 安装mysql 8.0.13(rpm)的教程详解

    这篇文章主要介绍了Centos7 安装mysql 8.0.13(rpm)的教程详解,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-11-11
  • 详谈mysql order by in 的字符顺序(推荐)

    详谈mysql order by in 的字符顺序(推荐)

    下面小编就为大家带来一篇详谈mysql order by in 的字符顺序(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • 点赞功能使用MySQL还是Redis

    点赞功能使用MySQL还是Redis

    本文主要介绍了点赞功能使用MySQL还是Redis,这是最近面试时被问到的1道面试题,本篇博客对此问题进行总结分享,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • 防止web项目中的SQL注入

    防止web项目中的SQL注入

    这篇文章介绍了防止web项目中的SQL注入,小编觉得挺不错的,现在分享给大家,也给大家做个参考。需要的朋友可以收藏下,方便下次浏览观看
    2021-12-12
  • mysql-5.5.28源码安装过程中错误总结

    mysql-5.5.28源码安装过程中错误总结

    介绍一下关于mysql-5.5.28源码安装过程中几大错误总结,希望此文章对各位同学有所帮助。
    2013-10-10
  • mysql 8.0.12 快速安装教程

    mysql 8.0.12 快速安装教程

    这篇文章主要为大家详细介绍了mysql 8.0.12的快速安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • MySQL的指定范围随机数函数rand()的使用技巧

    MySQL的指定范围随机数函数rand()的使用技巧

    这篇文章主要介绍了MySQL的指定范围随机数函数rand()的使用技巧,需要的朋友可以参考下
    2016-09-09
  • mysql存储中使用while批量插入数据(批量提交和单个提交的区别)

    mysql存储中使用while批量插入数据(批量提交和单个提交的区别)

    这篇文章主要介绍了mysql存储中使用while批量插入数据(批量提交和单个提交的性能差异),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08

最新评论