关联子查询调优系列 | 如何使用通用表表达式(CTE)

前言

在日常的数据库开发和维护中,关联子查询常被用于实现基于主查询条件的动态过滤逻辑。然而,尽管其语法直观易懂,若未妥善优化,关联子查询极易导致性能问题,尤其是在处理大数据量时。本文将深入探讨如何通过通用表表达式(CTE)对这类查询进行重构,将嵌套逻辑提取为独立可复用的中间结果,以降低查询的执行次数,进而实现显著的性能提升。

作用原理

CTE 允许您创建临时结果集,可在查询中多次引用。将关联子查询的结果存储在 CTE 中,以避免多次计算,并使查询更具可读性。


适用场景

适用于需要多次引用相同子查询结果的情况,以提高可读性和代码复用性。CTE 并不总是导致性能提升,但可以改善查询的可维护性。

  • 多次引用相同的子查询结果:当您需要在查询中多次引用相同的子查询结果时,使用 CTE 可以避免多次执行相同的子查询。这有助于提高查询性能,并提高查询的可读性和维护性。
  • 提高查询可读性:复杂的关联子查询可能会降低查询的可读性。使用 CTE 可以将子查询的结果以更易读的方式命名和引用,使查询更易于理解和维护。
  • 将逻辑分解为更小的部分:有时,将查询逻辑分解为更小的、可重用的部分可以使查询更易于管理。CTE 允许将查询分解为更小的块,每个块执行特定的任务。
  • 递归查询:CTE 特别适用于处理递归查询,因为它们允许在查询内部引用自身。递归查询通常需要多次引用相同的查询逻辑。
  • 避免子查询嵌套过深:有时,嵌套子查询会导致查询过于复杂。使用 CTE 可以将子查询逻辑分解为更清晰和易于理解的部分,避免过深的嵌套。


优化示例

原始关联子查询 SQL 语句及性能情况请参考关联子查询 SQL 示例。

使用 WITH 子句

WITH CustomerSales AS (
    SELECT
        ss.ss_customer_sk,
        SUM(ss.ss_ext_sales_price) as total_sales
    FROM store_sales ss
    GROUP BY ss.ss_customer_sk
    HAVING total_sales > 10000
)

SELECT c.c_customer_id
FROM customer c
JOIN CustomerSales cs ON c.c_customer_sk = cs.ss_customer_sk
ORDER BY c.c_customer_id
LIMIT 10;

性能对比

使用通用表表达式(CTE)的 with 子句将关联子查询保存为一个表达式,在与著查询进行连接,减少了子查询的执行次数。

使用 CTE 优化之后的执行时间为 8.1s,对于原始关联子查询语句优化了约 2.4 倍

image.png


评论
登录后可评论
发布者
星小环分享号
官方
文章
193
问答
253
关注者
27
banner
关注星环科技
获取最新活动资讯

加入TDH社区版技术交流群

获取更多技术支持 ->

扫描二维码,立即加入