PostgreSQL 提升子连接和 ORACLE 子查询展开
时间:2023-03-18
本文章向大家介绍PostgreSQL 提升子连接和 ORACLE 子查询展开,主要内容包括一、需要了解的概念:、二、in 子连接、使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
查询优化器对子查询一般采用嵌套执行的方式,即父查询中的每一行,都要执行一次子查询,这样子查询会执行很多次,效率非常低。
例如 exists、not exists 逐行取出经行匹配处理,项目中使用子查询的地方非常多,如何写出高效的sql,掌握子查询的优化是非常有必要的。
一、需要了解的概念:
PostgreSQL数据库基于子查询所在的位置和作用的不同,将子查询细分成了两类,一类称为子连接(SubLink),另一类称为子查询(SubQuery)。
如何区分子连接和子查询?
通常而言,如果它是以范围表的方式存在的,那么就称为子查询。
explain
select e1.*
from emp e1,
(select * from emp where deptno = 10) e2
where e1.empno = e2.empno
Hash Join (cost=1.21..2.40 rows=3 width=41)
Hash Cond: (e1.empno = emp.empno)
-> Seq Scan on emp e1 (cost=0.00..1.14 rows=14 width=41)
-> Hash (cost=1.18..1.18 rows=3 width=5)
-> Seq Scan on emp (cost=0.00..1.18 rows=3 width=5)
Filter: (deptno = '10'::numeric)
如果它以表达式的方式存在,那么就称为子连接。
-- 子链接1
explain
select e.empno, (select avg(sal) from emp e1 where e.deptno = e1.deptno)
from emp e
Seq Scan on emp e (cost=0.00..17.94 rows=14 width=37)
SubPlan 1
-> Aggregate (cost=1.19..1.20 rows=1 width=32)
-> Seq Scan on emp e1 (cost=0.00..1.18 rows=5 width=5)
Filter: (e.deptno = deptno)
-- 子链接2
explain
select *
from emp e1
where sal in (select sal from emp where e1.deptno = 10)
Seq Scan on emp e1 (cost=0.00..9.43 rows=7 width=41)
Filter: (SubPlan 1)
SubPlan 1
-> Result (cost=0.00..1.14 rows=14 width=5)
One-Time Filter: (e1.deptno = '10'::numeric)
-> Seq Scan on emp (cost=0.00..1.14 rows=14 width=5)
一般情况下,子连接的执行效率往往是比子查询低很多,因为子连接是逐行处理,会产生filter,而PostgreSQL 优化器会在某些情况下对子连接进行提升为子查询,从而对filter操作进行消除,提升查询效率。
二、in 子连接
** in 子连接提升子查询写法:**
explain select * from emp where deptno in (select deptno from dept);
Hash Join (cost=1.09..2.31 rows=14 width=41)
Hash Cond: (emp.deptno = dept.deptno)
-> Seq Scan on emp (cost=0.00..1.14 rows=14 width=41)
-> Hash (cost=1.04..1.04 rows=4 width=5)
-> Seq Scan on dept (cost=0.00..1.04 rows=4 width=5)
可以被提升,优化器相会内部重写成内连接。
explain select emp.* from emp inner join dept on emp.deptno = dept.deptno;
Hash Join (cost=1.09..2.31 rows=14 width=41)
Hash Cond: (emp.deptno = dept.deptno)
-> Seq Scan on emp (cost=0.00..1.14 rows=14 width=41)
-> Hash (cost=1.04..1.04 rows=4 width=5)
-> Seq Scan on dept (cost=0.00..1.04 rows=4 width=5)
表明此 in 子连接被优化,优化后采用hash join算法。
in 子连接无法提升子查询写法:
explain select * from emp e1 where sal in (select sal from emp where e1.deptno = 10);
Seq Scan on emp e1 (cost=0.00..9.43 rows=7 width=41)
Filter: (SubPlan 1)
SubPlan 1
-> Result (cost=0.00..1.14 rows=14 width=5)
One-Time Filter: (e1.deptno = '10'::numeric)
-> Seq Scan on emp (cost=0.00..1.14 rows=14 width=5)
explain select * from emp e1 where sal not in (select sal from emp );
Seq Scan on emp e1 (cost=1.18..2.35 rows=7 width=41)
Filter: (NOT (hashed SubPlan 1))
SubPlan 1
-> Seq Scan on emp (cost=0.00..1.14 rows=14 width=5)
表明此 in 子连接未被优化,无法消除filter操作,只能逐行处理。
原文地址:https://www.cnblogs.com/yuzhijian/p/17229200.html
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解