从Join的实现窥探MySQL迭代器

网友投稿 744 2023-04-24

从Join的实现窥探MySQL迭代器

从Join的实现窥探MySQL迭代器

以如下left join查询语句为范例:

select * from t1 left join t2 on t1.c=t2.a ;

以下初始化数据:

1 DROP TABLE IF EXISTS `t1`;2 CREATE TABLE `t1` (3 `a` int DEFAULT NULL,4 `b` varchar(20) DEFAULT NULL5 )6 INSERT INTO `t1` VALUES (1, 'a');7 INSERT INTO `t1` VALUES (1, 'b');8 INSERT INTO `t1` VALUES (4, 'a');9 INSERT INTO `t1` VALUES (5, 'a');10 11 DROP TABLE IF EXISTS `t2`;12 CREATE TABLE `t2` (13 `c` int DEFAULT NULL,14 `d` varchar(20) DEFAULT NULL15 )16 INSERT INTO `t2` VALUES (9, 'i');17 INSERT INTO `t2` VALUES (1, 'i');18 INSERT INTO `t2` VALUES (2, 'i');19 INSERT INTO `t2` VALUES (3, 'i');

1.处理join的yacc入口

在sys_yacc.yy​文件内解析t1 left join t2 on t1.c=t2.a;对应处理位置。

1 table_reference outer_join_type table_reference ON_SYM expr2 {3 $$= NEW_PTN PT_joined_table_on($1, @2, $2, $3, $5);4 }

其中outer_join_type对应。

1 outer_join_type:2 LEFT opt_outer JOIN_SYM { $$= JTT_LEFT; }3 | RIGHT opt_outer JOIN_SYM { $$= JTT_RIGHT; }

入参处理在函数T_joined_table_on内。

2.移步到函数PT_joined_table_on

函数PT_joined_table_on​将输入join的左右表加入context内,并调用add_join_on将on内的条件加入右表,记录后续数据过滤条件。

4.优化器操作,生成access_paths

sql_select.cc​内函数bool Sql_cmd_dml::execute(THD *thd)​函数内主要操作为函数execute_inner​,在函数execute_inner内首先会对当前的执行优化操作。

调用查询表达式Query_expression​的优化器unit->optimize​,此函数中会对该Query_expression​的内的每个查询块query_block分别先进行优化操作。

查询块内函数bool JOIN::optimize()​内会将每个查询块优化生成查询执行计划 ,具体执行函数为函数JOIN::create_access_paths()内create_root_access_path_for_join()​函数,以当前查询为例在函数create_root_access_path_for_join​内根据参数条件主要调用ConnectJoins函数。

在函数ConnectJoins​内调用FindSubstructure判断是join类型内连接、外连接、半链接等类型。

根据FindSubstructure​返回join类型调用相应的函数生成path,当前查询为例执行调用CreateHashJoinAccessPath生成path。

至此查询块query_block​的优化操作和path生成完成,查询块优化操作完成后再执行整体表达式Query_expression的优化和path的生成,因为目前范例仅为一个查询块,所以当前无需再做整体表达式的优化和path生成。

5.创建迭代器iterator

根据上一步生成的path调用CreateIteratorFromAccessPath函数生成迭代器,用于循环操作各表数据。

在此函数内会根据path的类型调用生成不同类型的迭代器,以目前范例为例,会调用迭代器类型为HashJoinIterator。

6.上述4、5步执行完成后,执行迭代器iterator

在函数execute_inner​内执行完成上述4、5步骤操作后主要继续执行unit->execute(thd)​函数,其对应执行查询表达式函数bool Query_expression::ExecuteIteratorQuery(THD *thd)。

函数Query_expression::ExecuteIteratorQuery​内主要执行m_root_iterator->Init()​,迭代器iterator初始化,当前范例为使用HashJoinIterator​类型迭代器,因此对应执行迭代器函数HashJoinIterator::Init()。

执行m_build_input->Init()​来初始右表table句柄,用于下面函数BuildHashTable()​内读取右表数据以便初始化返回数据存储表hashtable​,值得注意的是BuildHashTable​函数内会根据处理流程调用SetReadingProbeRowState设置执行状态用于引导后续迭代器iterator执行流程。

函数内最后调用InitProbeIterator​执行m_probe_input->Init()初始左表table句柄用于下面函数读取左表数据。

上面操作完成后执行m_root_iterator->Read()​函数,以当前查询为范例其对应int HashJoinIterator::Read()​函数,执行过程中根据前面SetReadingProbeRowState​设置的流程状态再选择对应的操作函数,以当前范例则会循环读取左表数据,而在操作函数内也会调用SetReadingProbeRowState​来设置迭代器iterator下一步操作,直至迭代器处理完成,其中在函数Query_expression::ExecuteIteratorQuery,每次读取一条成功后就会调用send_data操作将结果发送至客户端,直至所有查询结果发送完成。

7.至此客户端收到相应显示查询结果。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:分页 + 模糊查询 有坑!你知道吗?
下一篇:字节二面:Redis 的大 Key 对持久化有什么影响?
相关文章