MySQL內核技術之「結果發送」

本節咱們主要討論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

相關文章
相關標籤/搜索