分布式数据库TiDB中优化器相关代码
来源:互联网 发布:windows一直系统还原 编辑:程序博客网 时间:2024/06/18 10:27
TiDB中优化器有关代码
TiDB的优化分为基于规则的优化(Rule Based Optimization)和基于代价的优化(Cost Based Optimization)。TiDB的优化器相关代码在 plan包中,这个包的主要工作是将 AST转换为查询计划树,树中的节点是各种逻辑算子或者是物理算子,对查询计划化的各种优化都是通过调用树根节点的各种方法,递归地对所有节点进行优化,并且会不断的对树中的节点进行转换和裁剪。
最重要的几个接口在 plan.go 中,包括:
Plan: 所有查询计划的接口
LogicalPlan:逻辑查询计划,所有的逻辑算子都需要实现这个接口
PhysicalPlan:物理查询计划,所有的物理算子都需要实现这个接口
逻辑优化的入口是 planbuilder.build(),输入是AST,输出是逻辑查询计划树。然后在这棵树上进行逻辑查询优化:
调用 LogicalPlan 的 PredicatePushDown 接口,将谓词尽可能下推
调用 LogicalPlan 的 PruneColumns 接口,将不需要的列裁减掉
调用 aggPushDownSolver.aggPushDown,将聚合算子下推到Join 之前
拿到逻辑优化后的查询计划树之后,会进行物理优化,代码的入口是对逻辑查询计划树的根节点调用 convert2PhysicalPlan(&requiredProperty{}),其中requiredProperty 是对下层返回结果顺序、行数的要求。
逻辑查询计划树从根节点开始,不断的递归调用,将每个节点从逻辑算子转成物理算子,并且根据每个节点的查询代价找到一条比较好的查询路径。
l Plan包下的一些代码
physical_plan_builder.go是根据逻辑查询计划制定出物理查询计划,其中定义了一些常量作为查询代价计算的一些权重
const(
netWorkFactor =1.5
netWorkStartFactor= 20.0
scanFactor =2.0
descScanFactor =5 *scanFactor
memoryFactor =5.0
hashAggMemFactor =2.0
selectionFactor = 0.8
distinctFactor = 0.8
cpuFactor = 0.9
aggFactor = 0.1
joinFactor =0.3
)
PhysicalPlan是一个接口,其中有一个函数为matchProperty,如果一个物理计划匹配所需的属性则用matchProperty计算其代价。matchProperty通常在convert2PhysicalPlan的结尾被调用。有一些物理计划没有实现matchProperty是因为没有属性用来匹配,这些物理计划将直接计算代价。如果一个物理计划没有匹配到所需的属性,则将其代价置为MaxInt64,这样它将不会被选为最后的物理计划。
match_property.go中大部分函数实现了接口方法matchProperty。
(1)
func (ts *PhysicalTableScan) matchProperty(prop *requiredProperty, infos ...*physicalPlanInfo) *physicalPlanInfo
PhysicalTableScan代表一个表扫描计划。首先查询代价为
cost := rowCount *netWorkFactor
如果有limit(即SQL语句中有limit)则为
cost = float64(prop.limit.Count+prop.limit.Offset) *netWorkFactor
如果requiredProperty中数组props长度为0(即所需属性为0),代价即为当前代价,计算结束。
否则,继续进行判断。如果requiredProperty中数组props长度为1且该属性为主键并且包含filter条件的话,代价则为
cost += rowCount *cpuFactor
然后计算结束。
否则,继续进行判断。如果此时有limit,进行addTopN操作,操作成功代价为
cost += rowCount *cpuFactor
操作失败代价为
cost = rowCount *netWorkFactor
然后计算结束。
如果以上条件都不满足,则代价为MaxFloat64。
(2)
func (is *PhysicalIndexScan) matchProperty(prop *requiredProperty, infos ...*physicalPlanInfo) *physicalPlanInfo
PhysicalIndexScan代表一个索引扫描计划
如果有limit,代价则为limit的数量乘以netWorkFactor,否则为行数乘以netWorkFactor
rowCount := infos[0].count
if prop.limit != nil {
rowCount = float64(prop.limit.Count)
}
cost := rowCount *netWorkFactor
如果查询需要的列不属于索引,DoubleRead为true,此时代价乘2
ifis.DoubleRead {
cost *= 2
}
如果requiredProperty中数组props长度为0(即所需属性为0),代价即为当前代价,计算结束。
否则继续,如果所有列都能匹配上,代价为
sortedCost := cost + rowCount*cpuFactor
计算结束。
否则继续,当前判断是否有limit,如果有且执行addTopN成功的话,代价为
cost += infos[0].count *cpuFactor
执行失败代价为
cost = infos[0].count *netWorkFactor
计算结束。
如果以上条件都不满足,则代价为MaxFloat64。
(3)
func(p *PhysicalHashSemiJoin) matchProperty(_ *requiredProperty, childPlanInfo ...*physicalPlanInfo) *physicalPlanInfo
PhysicalHashSemiJoin代表一个用于semi join的hash join,该物理计划代价为两个子计划代价的和。
(4)
func(p *PhysicalMergeJoin) matchProperty(prop *requiredProperty, childPlanInfo ...*physicalPlanInfo) *physicalPlanInfo
PhysicalMergeJoin代表一个用于inner/outer join的merge join,该物理计划代价为两个子计划代价的和。
(5)
func(p *PhysicalHashJoin) matchProperty(prop *requiredProperty, childPlanInfo ...*physicalPlanInfo) *physicalPlanInfo
PhysicalHashJoin代表一个用于inner/outer join的hash join,代价为两个子计划代价的和,如果右边是小表的话则代价为
cost += lCount +memoryFactor*rCount
否则代价为
cost += rCount + memoryFactor*lCount
(6)
func(p *Union) matchProperty(_ *requiredProperty, childPlanInfo ...*physicalPlanInfo) *physicalPlanInfo
Union代表一个Union计划,其代价为所有子计划的代价和。
今年5月-8月,TiDB团队开发了新的基于代价的优化(Cost Based Optimization)
ps:这篇文章是之前好久就已经写好了,其中大部分资料来自TiDB官网,代码来自于github。
- 分布式数据库TiDB中优化器相关代码
- 分布式数据库TIDB
- PingCAP 分布式数据库TiDB介绍
- TiDB:支持MySQL协议的分布式数据库解决方案
- TiDB:支持 MySQL 协议的分布式数据库解决方案
- 为分布式监控系统Zabbix配置TiDB数据库
- 分布式数据库TiDB架构及资源调度隔离简介
- 对标 Google , PingCAP 分布式数据库 TiDB 火爆开源社区
- 【分布式数据库】【相关】
- TiDB
- 为zabbix分布式监控应用配置TiDB
- 代码优化相关
- 数据库优化相关
- 数据库优化相关建议
- 数据库优化相关
- 数据库相关设计优化
- 数据库相关优化方案
- 数据库MySQL优化相关
- 如何规划系统的架构
- 99%的产品经理不知道的秘密:如何招程序猿喜欢?
- BZOJ2819 Nim
- 体验产品一 | 悦动圈VS咕咚竞品分析报告
- 如果你读不完凯文凯利的《必然》,至少读完这120条书摘
- 分布式数据库TiDB中优化器相关代码
- python连接
- 怎样让静态库(static library)中的category变得可用
- 试玩UML(User Mode Linux)
- 柱状图
- HTTP Status 400
- POJ 1376 Robot
- java分布式任务调度xxl-job
- DB2 SQL Error: SQLCODE=-668, SQLSTATE=57016 解决方案