【SQL 优化器技术系列】 公共子表达式消除

Oracle 2005 年出了一个 30 多页的小册子,《Query Optimization in Oracle Database10g Release 2》,介绍了常见的优化器技术。

我是做 SQL 执行的,优化部分只了解皮毛,从没有系统学习过。本系列逐个学习和介绍,自我提升,也帮助他人。

这个技术原理也很简单,初中就学习过:

(a * b) + (a * c) = a * (b + c)

在这个式子里,如果 a 是一个常量,那么这个变换没什么意义,但是考虑如果 a 是一个函数,改写成:

(f(x) * b) + (f(x) * c) = f(x) * (b + c)

显然,式子右侧更加高效,它把 f(x) 抽取出来,只需计算一次即可。

回到 SQL 里看看什么是公共子表达式消除:

SELECT * FROM EMP, DEPT
WHERE
(EMP.DEPTNO = DEPT.DEPTNO AND LOC = 'DALLAS' AND SAL > 100000)
OR
(EMP.DEPTNO = DEPT.DEPTNO AND LOC = 'DALLAS' AND JOB_TITLE = 'VICE PRESIDENT')

这里,EMP.DEPTNO = DEPT.DEPTNO AND LOC = 'DALLAS' 就是上面式子里的 f(x),改写后变成:

SELECT * FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO AND LOC = ‘DALLAS’ AND
(SAL > 100000 OR JOB_TITLE = 'VICE PRESIDENT');

改写之前,从 DEPT 吐出的每一行数据都会计算两次 LOC='DALLAS' 表达式,改写后只需要计算一次。

NOTE:理解这个技术,一定要知道“计算机是非常愚蠢”的,你不帮它提取,它就算两遍!我们人类遇到这种问题时,都会自动做公共表达式抽取,计算机可不会。不过,一旦你教会了计算机这个规则,它可以做得比人类好得多。为什么?假设这个表达式有 10 页纸,人类可能就观察不出来了,计算机还是能轻松解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值