查询优化
如何设计一个简单查询优化器
逻辑优化:定义一些启发式的逻辑优化规则进行等价变化
物理优化:先决定访问路径,再定义一些启发式的物理优化规则决定连接顺序与连接方式
基于规则的优化
逻辑优化(代数优化)启发式规则:
- 选择下推(谓词下推)
- 将复杂谓词划分为多个简单谓词
- 投影下推
- 投影合并
- 投影和选择(其他运算)同时进行
- 将选择和笛卡尔积结合为一个连接算子
- 子查询上拉,把某些子查询重写为等价的多表连接操作(子查询展开)
- 条件化简
- 移除未使用的字段
物理优化启发式规则:
-
选择操作(路径选择操作)的启发式规则
-
对于小关系(<1000行),使用全表顺序扫描,即使选择列上有索引
-
对于大关系:
- 对于选择条件是主码等值的查询,查询结果最多是一个元组,可以选择主码索引;
- 对于选择条件是非主属性等值查询、非等值查询、范围查询,估算查询结果的元组数目比例较小(<10%)可以使用索引扫描方法, 否则全表顺序扫描;
-
AND连接的选择条件:
- 如果有涉及这些属性的组合索引,优先采用组合索引扫描方法 ;
- 如果某些属性上有一般的索引,优先采用选择率最低的一个索引;
-
OR连接的选择条件:一般使用全表顺序扫描;
-
-
连接操作的启发式规则:
- 如果两个表都已经按照连接属性排序,优先采用排序-合并连接
- 如果前表较小,后表在连接属性上有索引,优先采用索引连接
- 否则采用块嵌套循环或散列连接
基于代价的优化
用于物理优化,通过估计磁盘存取块数(I/O代价)、处理机时间(CPU 代价)等的代价,选择最优的物理执行计划。
维护的统计信息:
-
对每个基本表:
- 该表的元组总数(N)
- 元组长度(l)
- 占用的块数(B)
- 占用的溢出块数(BO)
-
对基表的每个列:
-
该列最大值、最小值
-
该列不同值的个数(m),和不同值的选择率(f)
-
如果不同值的分布是均匀的,f=1/m
-
如果不同值的分布不均匀,则每个值的选择率=具有该值的元组数/N
基于Count-Min Sketch统计不同值的选择率(f)
不同列的取值不是独立的,不同列的选择率直接相乘,可能导致估算不准确。
如第一列中取值是人的选择率为1,第二列中取值是男人的选择率为0.5,
-
-
该列上是否已经建立索引和索引类型(B+树索引、Hash索引)
-
-
对索引(如B+树索引):
- 索引的层数(L)
- 索引的叶结点数(Y)
- 不同索引值的个数,和不同索引值的选择基数(S,有S个元组具有某个索引值)
访问路径选择代价模型:
-
全表扫描的代价估算(基本表大小为B块)
- 全表扫描算法的代价 cost=B
- 如果选择条件是主码=值,平均搜索代价 cost=B / 2
-
索引扫描的代价估算(B+树,层数为L)
- 如果选择比较条件是主码=值,需要存取从根结点到叶结点L块,再加上基本表中该元组所在的那一块, cost = L + 1
- 如果选择比较条件是非主码=值,S是索引的选择基数(有S个元组满足条件,选择率) ,最坏的情况下,满足条件的元组可能会保存在不同的块上,此时,cost = L + S
- 如果选择比较条件是>,>=,<,<=操作,cost = L + 访问的叶节点块
连接代价模型:
- 嵌套循环
- 散列连接
- 排序-归并连接
基于代价的连接顺序搜索策略:
- 枚举
- DP算法
左深树:每个连接算子的右侧输入是一个关系(基本表),而不是连接后的中间结果,可以进行流水线的连接操作(子结点连接产生的记录可以马上送往父结点进行下一个连接算子,而不用等所有记录连接完成)