飞利浦·斯塔克|庖丁解牛|图解 MySQL 8.0 优化器查询转换篇( 六 )
4 应用当前查询块转换(apply_local_transforms)
该函数在flattern subqueries之后 , bottom-up调用 , 主要分几个步骤:
删除无用列(delete_unused_merged_columns)
如果查询块已经删除了一些derived tables/views , 遍历SELECT列表的列 , 删除不必要的列
简化JOIN(simplify_joins)
该函数会把Query_block中的top_join_list的嵌套join的简化为扁平化的join list 。 嵌套连接包括table1 join table2 , 也包含table1 (table2 table3)这种形式 。 如果所示的简化过程:
分区表的静态剪枝(prune_partitions)
由于剪枝根据HASH/RANGE/LIST及二级分区都有不同 , 这里简单介绍下剪枝过程 , 现有prune_partitions是在prepare和optimize阶段会被调用 , 某些常量子查询被评估执行完 。
struct TABLE { ...... partition_info *part_info{nullptr; /* Partition related information */ /* If true all partitions have been pruned away */ bool all_partitions_pruned_away{false; ...... SQL tranformation phaseSELECT_LEX::apply_local_transforms--prune_partitionsfor example select * from employee where company_id = 1000 ;SQL optimizer phaseJOIN::prune_table_partitions--prune_partitions ------based on tbl-join_cond_optim() or JOIN::where_condfor example explain select * from employee where company_id = (select c1 from t1); 举例下面RANGE剪枝的过程: root:refCREATE TABLE R2 ( -a INT -d INT -) PARTITION BY RANGE(a) ( -PARTITION p20 VALUES LESS THAN (20) -PARTITION p40 VALUES LESS THAN (40) -PARTITION p60 VALUES LESS THAN (60) -PARTITION p80 VALUES LESS THAN (80) -PARTITION p100 VALUES LESS THAN MAXVALUE -);Query OK 0 rows affected (0.09 sec)root:refSelect * From R2 where a40 and a80; 剪枝详细过程如下: 由于剪枝需要根据不同条件产生的pruning结果进行交集 , 因此剪枝过程中需要使用read_partitions这样的bitmap来保存是否使用该对应分区 。 另外剪枝过程类似迭代判断 , 因此引入了part_iterator来保存开始、结束和当前 , 以及对应需要获取区间范围的endpoint函数和获取下一个值next的迭代器函数 。 这里巧妙的运用了指针 , 来兼容不同分区类型Hash/Range/List类型 , 如下图所示:
获取join_cond或者m_where_cond的SEL_TREE红黑树(get_mm_tree) 调用find_used_partitions来获取满足的分区 , 对于SEL_TREE的每个区间(interval):1. 获取区间的左右端点 2.从左边继续获取下一个满足的分区 , 直到到右边端点结束 , 每次调用完满足条件的分区需要使用bitmap_set_bit设置该分区在part_info-read_partitions上的位点 。find_used_partitions是根据SEL_TREE的结构进行递归 , 如图从左到右遍历next_key_part(and condition) , 然后再遍历SEL_TREE的左右(也就是上下方向 , or condition)深度递归 。(start) | $ | Partitioning keyparts $ subpartitioning keyparts | $ | ... ... $ | | | $ | +---------+ +---------+ $ +-----------+ +-----------+ \\-| par1=c1 |--| par2=c2 |-----| subpar1=c3|--| subpar2=c5| +---------+ +---------+ $ +-----------+ +-----------+ | $ | | | $ | +-----------+ | $ | | subpar2=c6| | $ | +-----------+ | $ | | $ +-----------+ +-----------+ | $ | subpar1=c4|--| subpar2=c8| | $ +-----------+ +-----------+ | $ | $ +---------+ $ +------------+ +------------+ | par1=c2 |------------------| subpar1=c10|--| subpar2=c12| +---------+ $ +------------+ +------------+ | $ ... $例如第一行(par1=c1 and par2=c2 and subpar1=c3 and subpar2=c5)的遍历的stack将是:in find_used_partitions(key_tree = \"subpar2=c5\") (***)in find_used_partitions(key_tree = \"subpar1=c3\")in find_used_partitions(key_tree = \"par2=c2\") (**)in find_used_partitions(key_tree = \"par1=c1\")in prune_partitions(...)然后是继续下面的条件 , 以此类推or(par1=c1 and par2=c2 and subpar1=c3 and subpar2=c6)or(par1=c1 and par2=c2 and subpar1=c4 and subpar2=c8)or(par1=c2 and subpar1=c10 and subpar2=c12) 下图来展示了pruning的结构和过程: 5 下推条件到Derived Table(push_conditions_to_derived_tables)
- 飞利浦·斯塔克|最便宜的小米 12 来了,2000 块左右
- 飞利浦·斯塔克|「手慢无」泰坦军团 C30SK PRO显示器 秒杀1299元
- 飞利浦·斯塔克|集五福卡又来了!支付宝提前开始布局了,神秘福卡限时领
- 应用案例集锦丨飞利浦数字标牌,让品牌形象锋芒毕露
- 飞利浦·斯塔克|原价买显卡时代即将来临!英伟达:今年火力全开加大显卡产能
- 飞利浦新款首发K歌回音壁B5856 在家也要热血KTV
- 作为一个很懒的RGB爱好者|飞利浦huesync家庭影院氛围灯
- 飞利浦·斯塔克|所有互联网公司都在赔钱卖菜,真正的原因你绝对想不到!
- 飞利浦·斯塔克|《2021中国互联网广告数据报告》发布,受反垄断监管影响,阿里巴巴、腾讯广告收入增长放缓,字节跳动或赶超
- 飞利浦·斯塔克|世界是虚拟的吗?马斯克:我们活在真实世界的概率不到十亿分之一