下面以leftjoin查询语句为例:select*fromt1leftjoint2ont1.c=t2.a;以下初始化数据:1DROPTABLEIFEXISTS`t1`;2CREATETABLE`t1`(3`a`intDEFAULTNULL,4`b`varchar(20)DEFAULTNULL5)6INSERTINTO`t1`VALUES(1,'a');7INSERTINTO`t1`VALUES(1,'b');8INSERTINTO`t1`VALUES(4,'a');9INSERTINTO`t1`VALUES(5,'a');1011DROPTABLEIFEXISTS`t2`;12CREATETABLE`t2`(13`c`intDEFAULTNULL,14`d`varchar(20)DEFAULTNULL15)16INSERTINTO`t2`VALUES(9,'i');17INSERTINTO`t2`VALUES(1,'i');18INSERTINTO`t2`VALUES(2,'i');19INSERTINTO`t2`VALUES(3,'i');1.处理join的yacc条目在sys_yacc.yy文件t1中解析leftjoint2ont1.c=t2.a;对应加工位置。1table_referenceouter_join_typetable_referenceON_SYMexpr2{3$$=NEW_PTNPT_joined_table_on($1,@2,$2,$3,$5);4}其中outer_join_type对应。1outer_join_type:2LEFTopt_outerJOIN_SYM{$$=JTT_LEFT;}3|RIGHTopt_outerJOIN_SYM{$$=JTT_RIGHT;}输入参数在函数T_joined_table_on中处理。2、移至函数PT_joined_table_on从PT_joined_table_on的声明可知,它继承了PT_joined_table函数,左右表赋值为PT_joined_table中定义的tr1和tr2。函数PT_joined_table_on将输入join的左右表添加到context中,并调用add_join_on将on中的条件添加到右表中,并记录后续的数据过滤条件。3、执行阶段的函数do_command(thd)对应执行函数intmysql_execute_command(THD*thd,boolfirst_level)。语句解析和对应参数保存后,进入函数intmysql_execute_command(THD*thd,boolfirst_level)。该函数根据之前解析的命令类型开关(lex->sql_command)调用相应的处理函数,比如以当前语句为例,查询命令解析为lex->sql_command=SQLCOM_SELECT,然后进入函数lex->m_sql_cmd->执行(thd);对应sql_select.cc中的函数boolSql_cmd_dml::execute(THD*thd)。4.优化器操作,在access_pathssql_select.cc中生成函数boolSql_cmd_dml::execute(THD*thd),函数中主要操作是函数execute_inner,在execute_inner函数中,会优先执行当前执行的优化操作。调用查询表达式Query_expression的优化器unit->optimize,该函数会先优化Query_expression中的每个查询块query_block。查询块中的函数boolJOIN::optimize()将优化每个查询块以生成查询执行计划。具体执行函数是函数JOIN::create_access_paths()中的create_root_access_path_for_join()函数。以当前查询为例,在函数create_root_access_path_for_join中,主要是根据参数条件调用ConnectJoins函数。在ConnectJoins函数中调用FindSubstructure判断是否是innerjoin、outerjoin、semi-link等连接类型,根据FindSubstructure返回的连接类型调用相应的函数生成路径。以当前查询为例,调用CreateHashJoinAccessPath生成路径。至此,查询块query_block的优化操作和路径生成就完成了。查询块优化操作完成后,进行整体表达式Query_expression的优化和路径的生成。因为目前的例子只是一个queryblock,所以目前不需要做整体的表达优化和路径生成。5、创建迭代器迭代器调用CreateIteratorFromAccessPath函数,根据上一步生成的路径生成迭代器,用于循环遍历各个表中的数据。在这个函数中,会根据路径的类型生成不同类型的迭代器。以当前示例为例,迭代器类型将被称为HashJoinIterator。6、以上4、5步完成后,执行函数execute_inner中的iteratoriterator完成以上4、5步后,主要继续执行unit->execute(thd)函数,对应执行查询表达式函数boolQuery_expression::ExecuteIteratorQuery(THD*thd)。函数Query_expression::ExecuteIteratorQuery主要执行m_root_iterator->Init(),初始化iterator迭代器,当前例子是使用HashJoinIterator类型的迭代器,所以对应执行迭代器函数HashJoinIterator::Init().执行m_build_input->Init()初始化右表句柄,用于在后面的函数BuildHashTable()中读取右表数据,以初始化并返回数据存储表hashtable。值得注意的是,BuildHashTable函数会根据处理流程调用SetReadingProbeRowState来设置执行状态,以指导后续的迭代器执行过程。最后在函数中调用InitProbeIterator执行m_probe_input->Init()初始化左表表句柄,供后面函数读取左表数据。以上操作完成后,执行m_root_iterator->Read()函数。以当前查询为例,对应于intHashJoinIterator::Read()函数。执行时,根据前面SetReadingProbeRowState设置的进程状态,选择相应的操作函数。当前例子中会循环读取左表数据,并在操作函数中调用SetReadingProbeRowState来设置迭代器的下一步操作,直到迭代器处理完成。其中,在函数Query_expression::ExecuteIteratorQuery中,每读取一个成功后,就会调用send_data操作将结果发送给客户端,直到发送完所有查询结果。7、此时,客户端收到相应的显示查询结果。
