本节咱们主要讨论COUNT的结果处理与发送。典型的SQL语句为:SELECT COUNT(*) FROM foo;数组
结果累加调用链多线程
JOIN::exec()--> do_select()--> sub_select()--> evaluate_join_record()--> end_send_group()--> init_sum_functions--> reset_and_add()--> aggregator_add()--> Item_sum_count::add()
返回结果调用链并发
JOIN::exec()--> do_select()--> sub_select()--> evaluate_join_record()--> end_send_group()--> send_data--> send_result_set_row()--> Item::send()--> Item_sum_count::val_int()
注意:上面的end_send_group
其实是evaluate_join_record()
中的这行代码:rc= (*qep_tab->next_select)(join, qep_tab+1, 0);
优化
整个逻辑是sub_select()
中有个大循环,每次读出一条数据,而后进行evaluate_join_record()
。在evaluate_join_record()
中进行where
判断等,而后调用end_send
或者end_send_group
进行最后处理。由于这里是COUNT
所以,使用end_send_group()
。end_send_group
调用reset_and_add
进行累加。lua
发送完毕调用链(这个执行完客户端就有数据显示了)spa
dispatch_command()--> thd->send_statement_status()
如今咱们来看看如何多结果处理流程进行改造。从上面分析能够看出,每次读出一条数据就要进入evaluate,调用end_send_group产看是否应该累加仍是累加已经完毕。所以咱们要在end_send_group
加入新的逻辑,累加过程不变,可是累加完毕后,并不发送而是把结果放入select->m_parallel_results
里,同时把done位置为true线程
而主线程要查看worker是否都完成了,即把结果放入select->m_parallel_results,若是是则进行全部的结果累加,仍是加到item_sum中的count上。而后走正常的流程。code
附录
MySQL的COUNT操做对应了Item_sum_count
类,这个类是基于Item_sum
类的。那么对应一个JOIN结构而言,里面包含了一个(实际上是2个)Item_sum:分别是。Item_sum_count就被赋给了Item_sum这个成员变量。
执行的累加结果存在Item_sum_count中的count变量里,结束后被返回给客户端。由于没有GROUP BY,因此返回的结果只有一条记录。
改造的方法:由于一个JOIN对应了query的上下文,优化后的结果,若是同时被不一样的thread执行,那么应该有多个count结果,而不是一个,这样咱们就能够增长一个标志位为parallel,同时增长Item_sum_count中的member:count数组,其数量对应了多少个thread。每一个thread执行的结果放在这对应的count中,执行完毕后worker thread退出,而由主thread统计结果并发送最后的count给client。it