使用WITH提高查询效率

     前两天的业务需求里需要关联好几张表出一个详单报表,这个需求其实很简单,但是数据量大,源表又不是分区表,就变得很头疼了。

     最初我的代码大概是这样子的:

select 
a.id,
a.name,
a.code,
b.type,
(
select p_name
from C c
where c.pid = b.pid
)
from A a, B b
where a.id = b.id and a.id > 1000;

     这样的话如果三个表数据量小就没事儿了,一会儿就跑出来了。但是我们的A表上亿,A一个id对应B里的好多个id,那么B的数据量就更大了。C也差不多,这样一来就要老命了。这个时候我想到了用with这个办法来减小数据量。

     WITH这个东西主要是产生一个临时的表,可以通过各种条件见小数据量,挑选需要的列,如此这般,数据量就会小很多。WITH没有办法提高效率,但是就是降低数据量,靠硬件的优势。修改以后的代码如下:

with AA as (select id, name, code, type from A where id > 1000),
BB as (select type, pid from B),
CC as (select p_name, pid from C)
select AA.id, AA.name, AA.code, BB.type, C.p_name
where AA.id = BB.id
and CC.pid = BB.pid;

     经过业务上跑了一遍,原本13个小时没有跑出来的过程,居然很快的跑出来了,我很欣慰。就在这里记录一下这个知识点,和大家分享。

### 3.1 性能对比分析 在SQL查询中,`WITH`子句(也称为CTE,Common Table Expression)与子查询在执行效率上存在一定的差异,这主要取决于具体的使用场景和数据库系统的优化机制。 在Oracle中,`WITH`子句自9.2版本引入后,被优化器视为内联视图或临时表[^1]。当一个子查询需要在多个地方被重复使用时,`WITH`子句可以避免重复计算,提升查询效率。这是因为在某些情况下,优化器可以将`WITH`子句中的结果缓存为临时表,从而避免多次执行相同的子查询。 相比之下,PostgreSQL中的不相关子查询通常不会成为性能瓶颈,因为它们会被优化器“拉起”并集成到主查询中。如果优化器没有进行这种集成,则执行器会以InitPlan的方式单独执行这些子查询,这可能会导致性能下降,尤其是在处理相关子查询时[^2]。 在Hive SQL中,`WITH`子句和临时表的性能差异更加明显。对于中间结果仅使用一次的场景,推荐使用`WITH`子句,因为它可以避免I/O操作,优化器会将其内联到主查询中。而对于中间结果被多次引用的场景,创建显式的临时表可能更优,因为这样可以避免重复计算,尤其是在处理大规模数据时[^3]。 ### 3.2 使用场景对比 - **`WITH`子句适用场景**: - 中间结果仅使用一次:使用`WITH`子句可以避免I/O操作,优化器会将其内联到主查询中。 - 小规模数据:由于`WITH`子句的结果通常在内存中处理,因此对于小规模数据处理速度更快。 - 提高代码可读性:`WITH`子句可以将复杂的查询分解为多个逻辑部分,提高SQL的可读性和可维护性。 - **子查询适用场景**: - 不相关子查询:在PostgreSQL中,不相关子查询通常会被优化器集成到主查询中,不会成为性能瓶颈。 - 简单的单次使用:如果子查询只需要在查询使用一次,且结构简单,可以直接使用查询。 ### 3.3 示例代码 以下是一个使用`WITH`子句的示例,展示了如何定义一个CTE并在主查询中引用它: ```sql -- 定义一个名为 TEMP_A 的 CTE WITH TEMP_A AS ( SELECT column1, column2 FROM some_table WHERE some_condition ) -- 在主查询中引用 TEMP_A CTE SELECT a.column1, a.column2, b.some_other_column FROM TEMP_A a JOIN another_table b ON a.common_column = b.common_column WHERE a.some_other_condition; ``` ### 3.4 总结 综上所述,`WITH`子句和子查询各有优劣。`WITH`子句在提高代码可读性和处理中间结果多次引用时表现更佳,而子查询在简单场景下依然有效。具体选择应根据实际需求和数据库系统的优化机制来决定。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值