一、前言
2025.08.07 线上收到测试同学反馈,几个商机客户在商机公海里搜索不到,需要协助查看。
一开始以为是对应销售同学没有配置好对应池,所以才搜索不到。
销管明确说已正确配置池,并提供搜索不到商机客户的 clientId。测试同学和产品同同学也一起尝试了,发现确实搜索不到。
反馈到我这,让帮忙排查下。
通过接口开始排查:
- 加密搜索是否有问题:邮箱搜索是先加密再搜索
- 查询 SQL 是否有问题:字段问题

发现有 userStatus 字段,使用 NOT IN 查询。
在线上使用相同 SQL,加上 userStatus not in ('Unbind','Blocked')确实搜索不到。
且对应 clientId 中 userStatus 的值是 NULL。

那就是这块有问题,正常客户的 userStatus 不能为 NULL。
且在 MySQL / ADB 中,当 userStatus 字段为 null 时,使用 NOT IN 搜索不到。
这是因为在 SQL 中,任何与 NULL 的比较操作(包括 IN 和 NOT IN)都会返回 NULL(未知),而不是 TRUE 或 FALSE。在 WHERE 子句中,只有返回 TRUE 的记录才会被包含在结果集中。
修正方法:
- 线上数据订正:将对应的数据的 userStatus 改为正常值
- 修改查询 SQL:支持 userStatus 为 NULL,SQL 如下
sql
SELECT * FROM customer
WHERE clientId = '123'AND (ownerId IS NULL OR ownerId = '') AND (userStatus IS NULL OR userStatus NOT IN ('Unbind','Blocked'))
Hotfix:找到原因,跟当时开发同学沟通并确定,让其先补数据,并让其事后TODO修复。
PS:这块是工作了8年的前阿里同学写的。基础不扎实,小问题也会放大。
二、小结
为什么很多人建议 MySQL 字段不要设置为 NULL?
主要原因并不是说 NULL 一定不好,而是它在实际使用中会带来一些性能、语义和维护上的问题。
-
NULL 的语义复杂:在 SQL 中,
NULL表示"未知"或"不存在",它不是 0、空字符串、false,也不是任何具体值。sql-- 这意味着在比较时,NULL 有特殊规则: SELECT * FROM customer WHERE userStatus = NULL; -- 永远返回空结果 SELECT * FROM customer WHERE userStatus IS NULL; -- 才能判断是否为 NULL -- 如果开发人员不熟悉这些规则,很容易写出错误的查询。 -
索引和性能问题:在 MySQL(尤其是 InnoDB)中,
NULL值会影响索引存储方式。- 对含有
NULL的列建立索引时,MySQL 会额外存储一个标志位来表示该值是否为NULL,这会增加索引空间占用。 - 某些情况下,
NULL会让索引选择性降低,影响查询优化器的执行计划。
- 对含有
-
聚合和统计的复杂性:
COUNT(column)不会统计NULL值,而COUNT(*)会统计所有行。sqlSELECT COUNT(status) FROM customer; -- 不统计 status 为 NULL 的行 SELECT COUNT(*) FROM customer; -- 统计所有行 -
存储上的差异:
NULL列会额外占用 1 bit 的空间来记录是否为NULL。
Tips:好的编程习惯可以避免很多低级错误。
Java 开发者都需要学习:《阿里巴巴Java开发规范》
