【GreatSQL 优化器 -12】make_tmp_tables_info
【GreatSQL 优化器-12】make_tmp_tables_info
一、make_tmp_tables_info 介绍
GreatSQL 的优化器对于聚合函数和窗口函数需要创建内部临时表来进行计算并输出最后结果,这个内部临时表又需要原始表来作为数据输入源,具体的代码处理在make_tmp_tables_info
函数实现。
下面用一个简单的例子来说明make_tmp_tables_info
是做什么的。
二、make_tmp_tables_info 代码解释
内部临时表在优化器的顺序都是排在最后面,因此在优化器最后阶段才创建临时表。但是所需临时表的个数在这之前的make_join_plan()
就计算出来了。这里面涉及到一个很重要的概念:ref_items
数组分片,这个存储的是不同层所有涉及的 Item,实现输入表和输出表不同的结果。这其中通过tmp_table_param
变量作为原始表和临时表之间的桥,进行不同表之间的值传递。每张临时表都有一个对应的tmp_table_param
变量。
表一:需要建立临时表的场景
表二:join->ref_items 数组分片
注:对于需要内部临时表的查询,输入的表和输出的表是不同的,因此需要切换表分片,让临时表的结果能以 Item 形式输出到客户端
表三:join->ref_items[REF_SLICE_TMP1]里面 Item 存放格式
注:详细说明见函数 change_to_use_tmp_fields_except_sums()
表四:REF_SLICE_SAVED_BASE 和 REF_SLICE_TMP1 的 item 之间关系
表五:Copy_func_type 类型
三、实际例子说明
接下来看最初的例子来说明上面的代码。
上面的临时表结构,可以看到 hidden 列是倒序存放的,可见列把 Item 转为 result_field 存放。
临时表 QEP_TAB 的tmp_table_param->items_to_copy
,这里通过tmp_table_param->copy_funcs()
就可以实现m_func
和m_result_field
之间的值传递。
REF_SLICE_SAVED_BASE 分片 Item 信息
REF_SLICE_TMP1 分片 Item 信息
以上值传递过程:
下面是最终的执行计划,可以看到临时表排序是在最后的。
四、总结
从上面优化器的步骤我们认识了优化器创建内部临时表的过程,以及知道了如何实现输入表和输出表不同的处理,还通过具体例子知道了临时表的结构以及值传递的过程,需要注意的是,创建内部临时表后会改变输入的 fields 值,从原始表的 Item 变为临时表的 Item,如果开发用到这个 fields 值的话,需要注意取值时机有可能取到临时表的值,更甚者临时表被释放后取值会导致 crash。
版权声明: 本文为 InfoQ 作者【GreatSQL】的原创文章。
原文链接:【http://xie.infoq.cn/article/b45428af7a6d3b46be27d28d7】。文章转载请联系作者。
评论