欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > 69 mysql 中 is null 的实现

69 mysql 中 is null 的实现

2025/9/26 7:15:20 来源:https://blog.csdn.net/u011039332/article/details/133394775  浏览:    关键词:69 mysql 中 is null 的实现

前言

Mysql 中我们偶尔会用到 字段为 NULL 的情况 

这时候 我们只能使用查询 “select * from tz_test_02 where field1 is null;” 来进行 field1 字段为 null 的行的查询 

然后如果是使用 “select * from tz_test_02 where field1 = null;” 你会发现查询 不出数据

但是如果是 mysql 的 NULL-safe equals 的运算符 “select * from tz_test_02 where field1 <=> null;” 又是可以查询出数据的, 我们这里 来调试一下 这个流程

 

测试数据表如下 

CREATE TABLE `tz_test_02` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`field1` varchar(128) DEFAULT NULL,`field2` varchar(128) DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE,KEY `field_1` (`field1`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8

 

测试数据如下 

b68e6d7a8d46212926d53a59a98c975c.png

 

 

select * from tz_test_02 where field1 = null;

扫描索引的情况 

在 mysql 估算扫描的行的时候, 会解析整个表达式, 比如到我们这里的 ”field1 = null”

类型为 EQ_FUNC, field 是字段 tz_test_02.field1, value 是比较的值 NULL

然后 这里的 EQUAL_FUNC 值得就是 Null-safe 比较运算符 “<=>”

mysql 和 NULL 比较的规则是除了 Null-safe 之外的其他运算符, 和 NULL 比较都是 false, 这里备注也说了 ”comparison with null always false”

然后在外面 更新 const_table_map 为 1, 然后 外层扫表 found_const_table_map 为 0

15cbd0130a8c9ea332c5b337bdaae3e3.png

 

然后外层 make_join_plan 的时候, 扫描了0条记录, 设置 zero_result_cause 的时候设置了错误原因, “no matching row in const table”

110fdd2f8883cd8cb0a14d5e30e74160.png

 

最终 JOIN::exec 主流程中发现 前面设置了 zero_result_cause, 直接拦截 仅仅响应表格的元数据回去

a58c03ba6372863bc44abf3bc45e1d17.png

 

 

select * from tz_test_02 where field2 = null;

扫描非索引的情况, 是需要全表扫描 

扫描之后, 这里的 “where field2 = null” 的处理为 Agg_comparator 这边的处理, 比较的两个操作数, 一个是 field2 字段, 另外一个是 Item_null

然后 Item_null::val_str 这边返回的数据 恒为 0, 因此 这个比较 恒不成立, 永远返回 -1

d45ef81c7f062ff0efb042bc01fd4d05.png

 

Item_null::val_str 的处理如下, 返回值恒为 0

cec852cd6752f50080ba81e392cc7c65.png

 

 

select * from tz_test_02 where field1 is null;

这个是扫描索引 

索引数据记录分别为 [(null, 5), (field1, 1), (field10, 10)]

然后这里 扫描的是索引记录 (null, 5), 然后比较的另一个操作数也是 null, 这里比较 返回 0, 可以响应数据 

5b3a0916bb31b83d5e7ed27c89ff602b.png

 

然后接着是索引记录 (field1, 1), 这里比较的 另一个操作数是 null

这里 显然 “field1” <> null 的, 因此会返回 -1 或者 1, 数据匹配不上 

9a5b335f3dd14fbd4ad5482d7d052502.png

 

 

select * from tz_test_02 where field2 is null;

首先这里是需要 全表扫描的

这里的判断方式就是获取给定的 字段 是否为 null, 根据 null bit 获取 

97479338e4d25831bda162d8691740a7.png

 

 

select * from tz_test_02 where field1 <=> null;

这个是扫描索引 

索引数据记录分别为 [(null, 5), (field1, 1), (field10, 10)]

然后这里 扫描的是索引记录 (null, 5), 然后比较的另一个操作数也是 null, 这里比较 返回 0, 可以响应数据 

125731ccfeb957f307e5028b5ece6c5b.png

 

然后接着是索引记录 (field1, 1), 这里比较的 另一个操作数是 null

这里 显然 “field1” <> null 的, 因此会返回 -1 或者 1, 数据匹配不上 

df93e6a6d1148872d7b51d386e4fe145.png

 

 

select * from tz_test_02 where field2 <=> null;

首先这里是需要 全表扫描的

这里的判断方式就是获取给定的 字段 是否为 null, 根据 null bit 获取 

这个是 mysql 中 Null-safe 匹配的比较方式, 这里 左操作数是字段 field2, 右操作数是 Item_null, 返回的数字恒为 NULL
最终根据字段的值是否为 NULL 进行判断 

比如这里遍历的是第一条记录 (1, field1, ”1”), 可以看到 是不满足查询条件的

c29c3d6fce21fa367b94623d81d21f7e.png

 

这里是第二条记录 (5, NULL, ”5”) , 可以看到 是不满足查询条件的

5d07f172cceefca0b2075b21734c7bb9.png

 

这里是第三条记录 (10, “field10”, NULL) , 可以看到 是满足查询条件的

e6f62215feeb10c93341e1a30c5f3292.png

 

因此 最终查询结果如下

4071c7a461693e540ac4db9b256e06fe.png

 

 

 

 

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词