从存储引擎读取一条记录之后,对 Or 连接的 N 个 Where 条件(N >= 2)调用 Item->val_bool(),只要其中一个返回值等于True,记录就匹配 Or 连接的 N 个 Where 条件 。
文章插图
我们来聊聊 MySQL 是怎么判断一条记录是否匹配 where 条件的 。
本文内容基于 MySQL 8.0.32 源码 。
正文准备工作创建测试表:
CREATE TABLE `t1` (`id` int unsigned NOT NULL AUTO_INCREMENT,`str1` varchar(255) DEFAULT '',`i1` int DEFAULT '0',`i2` int DEFAULT '0',PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
插入测试数据:INSERT INTO t1(str1, i1, i2) VALUES('s1', NULL, NULL),('s2', 20, NULL),('s3', 30, 31),('s4', 40, 41),('s5', 50, 51),('s6', 60, 61),('s7', 70, 71),('s8', 80, 81);
示例 SQL:select * from t1where i2 > 20 and (i1 = 50 or i1 = 80)
整体介绍在源码中,where 条件会形成树状结构,示例 SQL 的 where 条件结构如下:
注意:这里的树状结构不是数据结构中的树 。
文章插图
我们可以从图中得到以下信息:
- Item_cond_and 代表 where 条件中的 and,连接 Item_func_gt 和 Item_cond_or 。
- Item_func_gt 代表 i2 > 20,其中 Item_field 包含 Field_long,代表 i2 字段,Item_int 代表整数 20 。
- Item_cond_or 代表 where 条件中的 or,连接两个 Item_func_eq 。
- 第 1 个 Item_func_eq 代表 i1 = 50,其中 Item_field 包含 Field_long,代表 i1 字段,Item_int 代表整数 50 。
- 第 2 个 Item_func_eq 代表 i1 = 80,其中 Item_field 包含 Field_long,代表 i1 字段,Item_int 代表整数 80 。
| > mysql_execute_command(THD*, bool) sql/sql_parse.cc:4688| + > Sql_cmd_dml::execute(THD*) sql/sql_select.cc:578| + - > Sql_cmd_dml::execute_inner(THD*) sql/sql_select.cc:778| + - x > Query_expression::execute(THD*) sql/sql_union.cc:1823| + - x = > Query_expression::ExecuteIteratorQuery(THD*) sql/sql_union.cc:1770| + - x = | > FilterIterator::Read() sql/iterators/composite_iterators.cc:79| + - x = | + > Item_cond_and::val_int() sql/item_cmpfunc.cc:5973| + - x = | + - > // 第 1 个 Item::val_bool()| + - x = | + - > // 代表 i2 > 20| + - x = | + - > Item::val_bool() sql/item.cc:218| + - x = | + - x > Item_func_gt::val_int() sql/item_cmpfunc.cc:2686| + - x = | + - x = > Arg_comparator::compare() sql/item_cmpfunc.h:210| + - x = | + - x = | > Arg_comparator::compare_int_signed() sql/item_cmpfunc.cc:1826| + - x = | + - x = | + > Item_field::val_int() sql/item.cc:3013| + - x = | + - x = | + - > Field_long::val_int() const sql/field.cc:3763 // i2| + - x = | + - x = | + > Item_int::val_int() sql/item.h:4934 // 20| + - x = | + - > // 第 2 个 Item::val_bool()| + - x = | + - > // 代表 i1 = 50 or i1 = 80| + - x = | + - > Item::val_bool() sql/item.cc:218| + - x = | + - x > Item_cond_or::val_int() sql/item_cmpfunc.cc:6017| + - x = | + - x = > // 第 3 个 Item::val_bool()| + - x = | + - x = > // 代表 i1 = 50| + - x = | + - x = > Item::val_bool() sql/item.cc:218| + - x = | + - x = | > Item_func_eq::val_int() sql/item_cmpfunc.cc:2493| + - x = | + - x = | + > Arg_comparator::compare() sql/item_cmpfunc.h:210| + - x = | + - x = | + - > Arg_comparator::compare_int_signed() sql/item_cmpfunc.cc:1826| + - x = | + - x = | + - x > Item_field::val_int() sql/item.cc:3013| + - x = | + - x = | + - x = > Field_long::val_int() const sql/field.cc:3763 // i1| + - x = | + - x = | + - x > Item_int::val_int() sql/item.h:4934 // 50| + - x = | + - x = > // 第 4 个 Item::val_bool()| + - x = | + - x = > // 代表 i1 = 80| + - x = | + - x = > Item::val_bool() sql/item.cc:218| + - x = | + - x = | > Item_func_eq::val_int() sql/item_cmpfunc.cc:2493| + - x = | + - x = | + > Arg_comparator::compare() sql/item_cmpfunc.h:210| + - x = | + - x = | + - > Arg_comparator::compare_int_signed() sql/item_cmpfunc.cc:1826| + - x = | + - x = | + - x > Item_field::val_int() sql/item.cc:3013| + - x = | + - x = | + - x = > Field_long::val_int() const sql/field.cc:3763 // i1| + - x = | + - x = | + - x > Item_int::val_int() sql/item.h:4934 // 80
【带你读 MySQL 源码:Where 条件怎么过滤记录?】FilterIterator::Read() 从存储引擎读取一条记录,Item_cond_and::val_int() 判断该记录是否匹配 where 条件 。从堆栈中可以看到,Item_cond_and::val_int() 的下一层有两个 Item::val_bool():
推荐阅读
- 绿松石|读完这个就是翡翠专家了
- 李维嘉|李维嘉为什么消失了?带你揭秘事实的背后
- 有MySQL了,为什么还硬要搭个MongoDB集群?
- 贾玲|贾玲没参加华表奖,沈腾不读颁奖词,疑已经知道好友没获奖
- 求职|研究生白读了?985研究生求职被拒,HR直言:我们只看第一学历
- 大学|考不上高中,读职高很丢脸吗?为什么家长非要孩子去读私立高中
- MySQL Router高可用搭建,你学会了吗?
- 一文读懂低代码
- 在 Meta 构建和部署 MySQL Raft
- ChatGPT的打字回复效果,原理是什么?我带你们实现!