查询优化概述
查询优化的两种方法:
- Rules:通过静态的条件判断,来重写查询。通过查看catalog而不是数据。
- Cost-based 枚举SQL的所有方案,并且预估成本然后选择成本低的。
查询优化的流水线
- SQL Rewriter 对SQL语句进行重写标记上额外信息(可选)
- Parser 进行编译,将sQL转化为语法树
- Binder 将SQL引用的符号转化为内部标记。比如
select * from foo
,会通过字符串"foo"来寻找相应的表。 - Logical Plan
- Tree Rewiter通过查询system catalog来进行优化
- 进入Optimizer,计算成本模型
- 生成物理计划
逻辑计划和物理计划的区别:
逻辑计划生成关系代数表达式,物理计划使用具体的操作符,是实际执行的底层逻辑。逻辑计划和物理计划不一定一一对应。
优化方法
Predicate Pushdown,通过提前执行谓语(从语法树上往下推),来减少工作量
- Selections:越早执行过滤操作越好。
- Projections: 提早执行,来最小化要执行的元组数据。
单一关系模型
- 顺序查询
- 聚簇索引
- 索引扫描
首先判断是否sargable(Search Argument Able)是否又对应索引。
现在大多数DBMS采用heuristics(启发式)而不是精确的模型。
一个sargable的query能很容易被启发式的模型执行。
多个关系模型
可以枚举的:
- 操作顺序
- 操作的方法:比如hash、sort-merge、nested loop…
- 拿到数据的方法:Index#1、Index#2、Seq Scan…
随着join数量的增加,可行的所有方法也会增加,故不能使用枚举,要限制搜索的数量来在可接受的时间内找到优化的方案。
- 自底向上:从nothing逐渐构建方案。例子:IBM System R, DB2, MySQL, Postgres, most open-source DBMSs
- 自顶向下:从想要的结果开始,然后从语法树上到下优化。例子:MSSQL, Greenplum, CockroachDB, Volcano
- 遗传算法 PostgreSQL(GEQ)
自底向上优化:System R