Skip to content

Commit 39f96b9

Browse files
committed
add: optimizer
1 parent 9827c72 commit 39f96b9

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed

22 optimizer/22-optimizer.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
## Optimizer I
2+
3+
1. 没有优化器能真正产生"最优"计划:是[NP-完全问题](http://www.matrix67.com/blog/archives/105)
4+
- 使用**估计(estimation)**来预测真实的开销
5+
- 使用**启发算法(heuristics)**来限制搜索空间
6+
7+
2. 逻辑代数表达式 ------optimizer-----> 最优的、等价物理代数表达式
8+
9+
- 关系代数表达式等价:两个关系代数表达式 在 **任何**(不能只是存在一个)合法的数据库实例上执行时 产生的元组集合相同。如:
10+
11+
(A ⨝ (B ⨝ C)) = (B ⨝ (A ⨝ C))
12+
13+
3. 五个设计原则
14+
- 最优化粒度 Optimization Granularity
15+
- 最优化时机 Optimization Timing
16+
- 预编译语句 Prepared Statements
17+
- 计划稳定性 Plan Stability
18+
- 搜索终点 Search Termination
19+
20+
4. Optimization Granularity:
21+
22+
- 单Query:
23+
- 搜索空间小
24+
- DBMS通常不会重用query之间的结果
25+
- 代价模型要考虑 是什么正在运行
26+
- 多Query:
27+
- 搜索空间大
28+
- 当有相似查询时,效率更高
29+
- 对于 数据/中间结果共享的情况 很实用
30+
31+
5. Optimization Timing
32+
33+
- 静态:
34+
-**执行前**,就选择最佳计划
35+
- 计划的质量 取决于 代价模型的准确度
36+
- 在prepared stmts的帮助下,能分摊到各个执行上
37+
- 动态:
38+
- 在query执行时,动态选择计划
39+
- 多执行时会有 重优化(re-optimize)
40+
- 难以实现
41+
- 适应式/混合式:
42+
- 用一种静态算法编译
43+
-**估计的误差 > 阈值**,重优化
44+
45+
6. Prepared Statements:三种选择
46+
47+
<img src="https://s2.ax1x.com/2019/09/17/nIe0HO.png" style="zoom:50%;" /> ==》<img src="https://s2.ax1x.com/2019/09/17/nIniFg.png" style="zoom:50%;" />
48+
49+
- 重优化:每次调用查询时都进行优化;难以重用已经存在的计划
50+
- 多计划:对于 params 不同值 生成多种plan
51+
- 平均计划:选择一个param的平均值,每次调用都用这个平均值
52+
53+
7. Plan Stability:三种选择
54+
55+
- Hints:允许DBA给optimizer一些优化提示
56+
- Fixed Optimizer Versions:
57+
- Backwards-Compatible Plans:
58+
59+
8. Search Termination:三种方式
60+
61+
- 定时:超过预设时间就停止优化
62+
- 阈值:直到找到 有比阈值更低代价的 plan
63+
- 穷尽:没有更多plan的变化方法
64+
65+
9. **最优化搜索策略**
66+
- 启发式
67+
- 启发式 + 基于代价的联接顺序搜索(Cost-based join search)
68+
- 随机化算法
69+
- 分层(Stratified)搜索:Planning is done in multiple stages
70+
- 统一(unified)搜索:Perform query planning all at once
71+
72+
10. 启发式:
73+
74+
- 尽早执行更严格的选择
75+
76+
- 在联接前执行所有选择
77+
78+
-**projection/predicate/limit** 下推(pushdown)
79+
80+
- 基于 基数的 联接顺序排序
81+
82+
-----
83+
84+
优点:
85+
86+
- 易实现,易调试
87+
- 对于简单查询很快
88+
89+
缺点:
90+
91+
- 在估计一个计划的预期成效时,需要依赖魔法常量
92+
- 当操作符有复杂的依赖时,几乎不能生成好的计划
93+
94+
11. 启发式 + 基于代价的联接顺序搜索:
95+
96+
- 初始优化使用静态的规则实现
97+
98+
- 然后使用动态规划 来决定表联接的最佳顺序: 使用 分治法搜索来 自底向上(Bottom-up) 规划
99+
100+
------
101+
102+
优点:
103+
104+
- 不用穷举搜索,通常也可以找到合理的执行计划
105+
106+
缺点:
107+
108+
- 同 启发式
109+
- left-deep join tree 不一定总是最优的(只能串行 join,并且由于产生了大量的中间临时表;还有另外一种join order叫做 **bushy join tree**,可以并行)
110+
- 需要考虑 代价模型中数据的物理性质
111+
112+
12. 随机化算法:(如Postgres的遗传算法)
113+
114+
- 在所有可能的执行计划构成的**解空间(solution space)**中随机搜索
115+
- 直到达到一个cost的阈值,或者经过一定长度的时间
116+
117+
------
118+
119+
模拟退火(simulated annealing)算法:
120+
121+
- 起始点为 纯启发式规则
122+
- 计算不同操作符的排列组合(如交换两个表的联接顺序):
123+
- 只要减少cost,接受之
124+
- 当cost增加时,**有小概率会接受**之(防止陷入到局部极优值的解,而找不到全局最优解)
125+
- 如果会违反结果正确性(比如排序的顺序),拒绝之
126+
127+
------
128+
129+
优点:
130+
131+
- 防止局部最优解
132+
- 低内存占用(不需要保留历史记录)
133+
134+
缺点:
135+
136+
- 当DBMS选了某个方案后,难以得知它为什么要这么选
137+
- 需要额外的工作来验证算法的确定性
138+
- 需要实现 正确性的判断规则(保证每一轮变化的结果都是正确的)
139+
140+
13. 分层搜索:
141+
142+
- 根据变换规则重写**逻辑查询(logical query)**:不考虑代价
143+
- 进入动态规划阶段来优化
144+
145+
-------
146+
147+
优点:
148+
149+
- 实际表现很好
150+
151+
缺点:
152+
153+
- 难以指定变换的优先级
154+
- 规则是大问题
155+
156+
14. 统一搜索:(以Volcano 优化器为例)
157+
158+
- 易于添加新的操作、新的等价规则
159+
- 把 数据的物理属性 当做第一成员
160+
- **自顶向下**:使用**分支定界(branch-and-bound)**搜索
161+
162+
----------
163+
164+
优点:
165+
166+
- 使用声明式(declarative)规则来进行变换
167+
- 更好地扩展性
168+
169+
缺点:
170+
171+
- 不易修改predicate
172+
- 在优化搜索前,所有等价类都被完全展开 来 生成所有的逻辑运算符
173+
174+
15. 查询优化很困难,甚至NoSQL一开始都没去实现它。
175+

0 commit comments

Comments
 (0)