SQL优化技巧 - 连接消除
· 阅读需 6 分钟
定义
连接消除(Join Elimination)通过在不影响最终结果的情况下从查询中删除表,来简化SQL以提高查询性能。通常,当查询包含主键-外键连接并且查询中仅引用主表的主键列时,可以使用此优化。
考虑下面的例子,
select o.* from orders o inner join customer c on c.c_custkey=o.o_custkey
订单表(orders)和客户表(customer)关联,且c_custkey是客户表的主键,那么客户表可以被消除掉,重写后的SQL如下:
select * from orders where o_custkey
连接消除的类型
内连接消除
内连接消除需要满足以下条件
-
事实上的主外键等值连接(父表的连接列非空且唯一)
-
父表的主键是查询中唯一被引用的父表的列
内连接消除的方式:
-
父表及主外键连接条件被消除
-
其他对于父表主键的引用被替换成外表的外键
-
如果外键可以为空且无其他的NFC条件1,则需要新增一个外键不为空的条件
案例:
-
原始SQL
select c_custkey from customer,orders where c_custkey=o_custkey
-
重写后的SQL
select orders.o_custkey from orders where orders.o_custkey is not null
外连接消除
外连接消除需要满足以下条件:
-
被消除的外连接必须是一个左外连接或右外连接
-
连接的条件必须存在一个由
AND
连接的主外键等值连接 -
内表的主键(非空且唯一)是查询中唯一被引用的内表的列
外连接消除的方式:
-
内表及其全部连接条件被消除
-
其他对于内表主键的引用被替换成内表的外键
案例1:PK只出现在连接条件中
- 原始SQL
select o_custkey from orders left join customer on c_custkey=o_custkey
- 重写后的SQL
select orders.o_custkey from orders
案例2:PK出现在其他地方
- 原始SQL
select orders.* from customer right join orders on c_custkey=o_custkey and c_custkey>20 where o_orderstatus='T'
- 重写后的SQL
select orders.* from orders where orders.o_orderstatus = 'T'