TiDB优化器架构
用户发出一条sql,通过协议层(mysql),传输到parse(将SQL解析成AST语法树这一样个东西),这个语法树是以树型的方式读取,这个AST接下来就到预处理(它主要是针对point query),如果是点查(这条语句可以直接通过唯一索引或者主键索引,只返回一行数据)的SQL 就不用逻辑优化或者物理优化,直接通过索引就把数据取出来了。 所以如果在pre process中发现是点查就直接推到 执行器执行。
如果不是点查,就入到逻辑优化(1. 是否又权限 2. 对象是否存在 3. SQL语句规整) 它是在SQL层面,生成逻辑的执行计划。逻辑执行计划并不能取数 然后 进入到物理优化(真正用于取数,如何得到比较好,走全表扫描好,还是走索引),它出来的成果就是一个叫做执行计划的东西。
那如何对比 执行计划,或者说哪个执行计划好,那就需要知道那条路径是最优,这个就需要通过统计信息来确定,物理优化层面是需要统计信息的(例如知道这张表有多少行,选择性是多少等等) 优化的重点是物理优化
执行计划会给到TiDB Executor,这个执行器负责执行SQL ,从存储中把数据取出来,
注意一点:TiDB是分布式的,它跟集中式不同的地方是它的数去是从哪个TiKV节点当中曲速,所以有一个 DisTributed Coprocessor,用去从哪个节点当中去取数
优化器重点三件事情:
1、预处理,最总要找点查
2、逻辑优化
3、物理优化 ,找到最优的执行计划
preprocess (优化器预处理)
预处理-》逻辑优化-》物理优化
- 针对点查(PointGet) 进行优化
- 构造初始的逻辑执行计划
- 常量折叠
- 表达式简化
- 子查询处理
对于点查(PointGet)
- 定义
- 单表的SELECT / UPDATE / DELETE 操作
- 只扫描表的1行或者0行,过滤条件为等值查询
- 返回的记录条数为1行或者0行
- 优化原因
- 优化方式较为单一
- 使用频率最高(OLTP)
- 如何优化
- 跳过下面的逻辑优化和物理优化,直接下推到SQL执行器
构造初始逻辑执行计划
逻辑优化
逻辑优化的规则
- 列剪裁
- 分区剪裁
- 聚合消除
- MAX/MIN优化
- 投影消除
- 外连接消除
- 谓词下推
- 连接顺序调整
列剪裁
谓词下推
很有帮助,特别是分布式数据库
尽量将计算下推到 数据节点上(TiKV)
左外连接: 右边表所有数据都显示,左边显示右边存在的行,没有的显示空
这个语句可以转换为下边的语句。 应为t2.val > 22 这个肯定就排除掉了空值
左外连接的规则: t1 表数据全部拿出来,t2表也拿出来 做一个left join. 先做连接,再做过滤,这个过滤是将数据全部拿出来在计算节点上操作。
左外连接转成内连接: 它是在kv节点上,现将数据过滤,再传到计算节点,进行内连接处理。
连接顺序调整
当写SQL的时候,t1 t2 t3 走表连接,它并不是根据from 来排列这个表,会根据一并的条件来找到最优的排列。
物理优化
物理优化的维度
物理优化的决策
索引选择
是否会使用索引覆盖
给定索引的抽取访问条件
- 过滤条件可能是多种多样的
- 选择单列索引还是复合索引
- 索引不能有false-negative 误判
- Index Merge 访问
将访问条件合并转化