cte功能oracle与pg执行模式对比
cte功能oracle与pg执行模式对比
- 一、引言
- 二、CTE的概念
- 三、CTE的基本语法
- 四、CTE的特点
- 五、CTE的使用场景
- 六、优化
- 执行模式
- 七、总结
我们的重点放在第七部分,前面是简单介绍,熟悉的读者可以跳过。
一、引言
公用表表达式(Common Table Expression,简称CTE)是SQL标准的一部分,它允许用户在查询中定义临时的结果集,这些结果集可以像普通表一样被引用。CTE在1999年被引入SQL:1999标准,并被大多数现代数据库管理系统所支持。本文将详细介绍CTE的概念、语法、特点以及使用场景,并提供详细的代码注释,以提高新手的可读性。
二、CTE的概念
CTE类似于一个临时视图,它在查询执行期间存在,并且在查询结束后自动销毁。CTE通常用于简化复杂的查询,特别是在涉及到递归查询或者需要重复使用相同查询结果的情况下。CTE通过将复杂查询分解为一系列更简单的查询,提高了代码的可读性和可维护性。
三、CTE的基本语法
CTE的基本语法结构如下:
-- 定义一个或多个CTE
WITH cte_name (column1, column2, ...)
AS
[ ] WITH cte_name (column1, column2, ...)
(-- CTE 查询SELECT column1, column2, ...FROM table_nameWHERE condition
)
-- 主查询
SELECT *
FROM cte_name WHERE condition;
在这个结构中,WITH关键字后面跟着一个或多个CTE定义,每个CTE由cte_name和括号中的列名列表组成。CTE的查询部分可以是任何有效的SELECT语句。在主查询中,CTE被当作一个临时表来使用。
四、CTE的特点
临时性:CTE只在定义它们的查询中有效,查询结束后,CTE自动消失。
可递归:CTE可以定义递归查询,这对于处理层次结构数据非常有用。
可读性:CTE使得复杂的SQL查询更加清晰,易于理解和维护。
重用性:在同一个查询中,CTE可以被多次引用,避免了重复的子查询。
灵活性:CTE可以包含多个SELECT语句,并且可以嵌套使用。
五、CTE的使用场景
简化复杂查询:CTE可以将复杂的查询逻辑分解为多个简单的步骤,使得查询更加易于理解和维护。
递归查询:CTE非常适合处理需要递归的查询,例如组织结构、文件系统路径等。
避免子查询:CTE可以替代一些复杂的子查询,使SQL语句更加简洁。
性能优化:在某些情况下,CTE可以帮助优化查询性能,尤其是在递归查询中。
六、优化
对于oracle我们使用后,可以看到属于非阻塞的输出情况。比如执行一个死循环的cte用例,如下:
```sql
with recursive t1(n) as
(select 1 from dualunion allselect n+1 from t1 where n > 0
)
select * from t1;
当执行上述语句后,随后在输出端看到持续的输出结果。用户体验感较好。
而对于pg数据库的cte功能,可以看到界面是卡死状态。没有输出结果。用户体验感较差。
当然这个体验感不足以说明产品的优劣。但是我们可以通过这个现象明白一个处理上逻辑的区分。
对于oracle是非阻塞的输出,那么它进行临时表存储时,每fetch一行结果,就写入临时表一行结果,同时向输出端产生一行结果。而对于pg来说,它的执行流程是将临时表全部准备完毕,才会执行fetch操作,向输出端产生数据。
而应用到一个一百万行数据的表时,pg单纯的查询就会产生写入+读出操作。而oracle只会产生写入操作,或者根据所需的引用次数不写入,仅内存中进行计算即可。节省了io花销。
执行模式
这两种数据库在处理递归CTE(或普通大结果集查询)时,其执行模式有本质区别:
● PostgreSQL (物化 Materialize): PG的优化器对CTE(尤其是WITH子句)的处理非常保守。在大多数情况下,PG会将CTE的结果完整地计算并物化(Materialize)到一个临时工作表中,之后才会从该临时表中读取数据返回给客户端。这就是为什么你在客户端看到的是“卡死”状态——数据库正在后台拼命计算并写入整个结果集,直到全部完成前,客户端拿不到任何一行数据。
● Oracle (流水线 Pipeline / 非阻塞): Oracle采用了一种更先进的流水线执行模式。查询的执行计划是一颗真正的生产者-消费者管道。也就是说,父操作(SELECT * FROM t1)可以源源不断地从子操作(递归部分select n+1 from t1 where n > 0)“拉取”已经计算出的数据行。一旦最顶层的操作产生了一行结果,它就可以立刻返回给客户端,而无需等待整个结果集计算完毕。
七、总结
CTE是一个强大的SQL工具,它提供了一种将复杂查询分解为更简单、更易于管理的部分的方法。通过使用CTE,开发者可以编写更清晰、更高效的SQL代码。无论是简化复杂查询、处理递归数据结构,还是优化性能,CTE都是一个不可或缺的工具。