标准答案

  1. CTE 的可读性、递归和数据修改语义与性能是不同问题;是否内联还取决于 PostgreSQL 版本、引用次数、递归属性和显式选项。
  2. MATERIALIZED 会先计算并物化结果,可能避免多次重复计算,但也可能阻断谓词下推、产生大中间结果并增加内存或临时文件。
  3. NOT MATERIALIZED 允许优化器把过滤条件继续下推,但多次引用时可能重复执行底层逻辑;应确认重复计算是否可接受。
  4. 递归 CTE、修改语句 CTE 和依赖执行顺序的写法有额外语义,不能只按普通 SELECT CTE 的经验推断。
  5. 改写前后要用代表性数据、峰值参数和 EXPLAIN 验证中间结果规模、缓冲、临时文件和总耗时。

题目解析

CTE 能让复杂查询按步骤表达,但“按步骤写”不一定代表数据库按步骤物化。版本和显式 materialization 选项会影响优化器是否继续合并查询。

性能问题通常来自中间结果:过滤没有下推导致先生成大量行,或者 NOT MATERIALIZED 让同一昂贵子查询被重复执行。要用计划和实际行数判断是哪一种。

面试回答应先说清业务语义是否依赖一次性结果、递归或写入顺序,再讨论内联和物化,不能把 CTE 直接归类为慢或快。

常见误区

  • 误区:认为所有 CTE 都是临时表。改正:CTE 是查询表达结构,是否物化要看版本、语义和执行计划。
  • 误区:看到 CTE 就机械改成子查询。改正:先确认问题是谓词下推、重复计算还是中间结果过大。
  • 误区:只看总耗时不看临时文件和中间行数。改正:CTE 的代价经常隐藏在排序、物化和重复扫描中。

作者信息