news 2026/8/10 9:18:47

/*+ MATERIALIZE */ 优化器提示在 WITH 子句中的使用验证

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
/*+ MATERIALIZE */ 优化器提示在 WITH 子句中的使用验证

Oracle /*+ MATERIALIZE */ 优化器提示在 WITH 子句中的使用验证

概述

/*+ MATERIALIZE */是 Oracle 数据库的优化器提示(Hint),核心作用是强制将 WITH 子句(公共表表达式,CTE)的查询结果物化到临时表中。当后续查询多次引用该 CTE 时,可直接复用临时表数据,避免重复执行子查询;即使仅引用一次,也能通过该 Hint 强制触发物化行为。

测试场景与验证

场景 1:重复引用子查询(非 WITH 子句)—— 无临时表物化

当相同子查询被多次直接引用(未封装到 WITH 子句)时,Oracle 优化器不会将子查询结果物化到临时表,每次引用都会重新执行子查询。

SELECTmain.cust_id,main.cust_name,main.order_summary,sub1.vip_countFROM(SELECTc1.cust_id,c1.cust_name,SUM(o.order_amount)ASorder_summaryFROM(SELECTcust_id,cust_name,cust_levelFROMcustomersWHEREtotal_consume>50000)c1LEFTJOINorders oONc1.cust_id=o.cust_idGROUPBYc1.cust_id,c1.cust_name)mainCROSSJOIN(SELECTCOUNT(*)ASvip_countFROM(SELECTcust_id,cust_name,cust_levelFROMcustomersWHEREtotal_consume>50000)c2WHEREc2.cust_level='VIP')sub1

执行计划结论:预估执行计划中未使用临时表空间,子查询被重复执行。
在这里插入图片描述

场景 2:重复引用 WITH 子句中的 CTE—— 触发物化

将重复执行的子查询封装到 WITH 子句中,多次引用该 CTE 时,Oracle 会自动将 CTE 结果物化到临时表。

WITHcAS(SELECTcust_id,cust_name,cust_levelFROMcustomersWHEREtotal_consume>50000)SELECTmain.cust_id,main.cust_name,main.order_summary,sub1.vip_countFROM(-- 第一次引用 cSELECTc1.cust_id,c1.cust_name,SUM(o.order_amount)ASorder_summaryFROMc c1LEFTJOINorders oONc1.cust_id=o.cust_idGROUPBYc1.cust_id,c1.cust_name)mainCROSSJOIN(-- 第二次引用 cSELECTCOUNT(*)ASvip_countFROMc c2WHEREc2.cust_level='VIP')sub1

执行计划结论:CTE 的结果集被物化到临时表中,后续引用直接复用临时表数据。

场景 3:单次引用 WITH 子句中的 CTE—— 不触发物化

若 WITH 子句中的 CTE 仅被引用一次,Oracle 优化器默认不会将结果集物化到临时表,而是直接执行子查询。

WITH c AS (SELECT cust_id, cust_name, cust_level FROM customers WHERE total_consume > 50000) SELECT main.cust_id, main.cust_name, main.order_summary FROM ( -- 仅一次引用 c SELECT c1.cust_id, c1.cust_name, SUM(o.order_amount) AS order_summary FROM c c1 LEFT JOIN orders o ON c1.cust_id = o.cust_id GROUP BY c1.cust_id, c1.cust_name) main

执行计划结论:预估执行计划中无临时表物化行为,CTE 子查询直接执行。

场景 4:单次引用 +/*+ MATERIALIZE */ Hint—— 强制物化

在 WITH 子句的 CTE 中添加/*+ MATERIALIZE */Hint,即使 CTE 仅被引用一次,也能强制 Oracle 将结果集物化到临时表。

测试 SQL

sql

WITH c AS (SELECT /*+ MATERIALIZE */ cust_id, cust_name, cust_level FROM customers WHERE total_consume > 50000) SELECT main.cust_id, main.cust_name, main.order_summary FROM ( -- 仅一次引用 c SELECT c1.cust_id, c1.cust_name, SUM(o.order_amount) AS order_summary FROM c c1 LEFT JOIN orders o ON c1.cust_id = o.cust_id GROUP BY c1.cust_id, c1.cust_name) main

执行计划结论:CTE 结果集被强制物化到临时表中。

场景 5:Hint 直接写在普通子查询中 —— 无效

/*+ MATERIALIZE */Hint 直接添加到非 WITH 子句的普通子查询中,无法触发物化行为。

执行计划结论:实验验证该方式无效,临时表物化未发生。

三、结论

  1. /*+ MATERIALIZE */仅对WITH 子句内的 CTE生效,直接写在普通子查询中无物化效果;
  2. WITH 子句中的 CTE 被多次引用时,Oracle 会自动物化结果到临时表;仅被单次引用时,默认不物化;
  3. 即使 CTE 仅单次引用,也可通过在 WITH 子句的 CTE 查询中添加/*+ MATERIALIZE */Hint,强制将结果集物化到临时表,适用于优化器判断失误时,未将结果集物化到临时表的情况。
  4. 需要复用子查询结果或优化执行效率的场景。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/7 15:43:42

语音转写还能识情绪?SenseVoiceSmall让你大开眼界

语音转写还能识情绪?SenseVoiceSmall让你大开眼界 你有没有遇到过这样的场景:会议录音转成文字后,发现“这个方案很好”和“这个方案很好!”——表面一样,语气却天差地别;又或者客服录音里突然响起一阵掌声…

作者头像 李华
网站建设 2026/8/7 15:46:22

2026年1月份国内3D打印行业11起融资,最高超亿元

3D打印技术参考统计发现,2026年1月国内3D打印行业共完成11起融资,覆盖消费级3D打印材料、设备,工业级3D打印设备、材料、制造服务,最高融资金额过亿。1. 中科煜宸完成C轮融资1月28日,南京中科煜宸激光技术有限公司完成…

作者头像 李华
网站建设 2026/8/7 15:44:49

Spring httpMessageConverter(四)

前端向后端传递参数的形式前端向后端传递参数的所有常见形式,以及这些形式在 Spring Boot 中对应的接收方式,这是实际开发中对接前后端的核心知识点。接下来我会按「参数传递位置」分类,详细讲解每种形式的特点、示例和后端接收方式&#xff…

作者头像 李华
网站建设 2026/8/7 15:45:06

测试用例--等价类划分、边界值法

一、测试用例/案例(test case/test instance) 1、定义:是在测试执行之前,由测试人员编写的指导测试过程的重要文档,主要包括:用例编号、测试目的、测试步骤(用例描述),预…

作者头像 李华
网站建设 2026/8/8 23:27:30

Python:代码对象

在 Python 的执行模型中,可执行代码并不是以字符串或抽象语法树的形式直接运行。源码在执行之前,会被编译为一种中间表示——代码对象(code object)。代码对象是 Python 对“可执行逻辑结构”的静态描述,是连接源码与运…

作者头像 李华
网站建设 2026/8/7 15:45:57

curl-发送请求 和 tcpdump与wireshark的介绍

文章目录1.客户端模拟请求工具1.1. curl-终端/命令行请求工具常见用法1.2. curl重要参数1.3. curl其他常用参数2. tcpdump wireshark2.1 tcpdump参数说明参数:表达式:2.2 wireshark总结✨✨✨学习的道路很枯燥,希望我们能并肩走下来&#xf…

作者头像 李华