news 2026/5/28 14:31:23

My-Oracle数据库优化-with as 分析优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
My-Oracle数据库优化-with as 分析优化

WITH AS (CTE) 优化改写原理

WITH AS公用表表达式(CTE, Common Table Expression),核心原理是:将子查询结果集临时存储在内存或临时段中,可被主查询多次引用


一、核心工作原理

sql

-- 原始写法:子查询执行2次 SELECT * FROM (SELECT * FROM orders WHERE status='ACTIVE') a UNION ALL SELECT * FROM (SELECT * FROM orders WHERE status='ACTIVE') b; -- CTE写法:只执行1次,结果复用 WITH active_orders AS ( SELECT * FROM orders WHERE status='ACTIVE' ) SELECT * FROM active_orders UNION ALL SELECT * FROM active_orders;

执行流程:

  1. 物化阶段:执行CTE中的查询,将结果集存入临时工作区

  2. 引用阶段:主查询中每次引用CTE,直接读取临时结果集

  3. 清理阶段:主查询执行完毕后,释放临时空间


二、关键优化场景

场景1:多表重复扫描

sql

-- ❌ 低效:同一张表扫描3次 SELECT (SELECT COUNT(*) FROM sales WHERE year=2024) AS total, (SELECT AVG(amount) FROM sales WHERE year=2024) AS avg_amount, (SELECT SUM(amount) FROM sales WHERE year=2024) AS sum_amount; -- ✅ 高效:只扫描1次 WITH sales_2024 AS ( SELECT amount FROM sales WHERE year=2024 ) SELECT (SELECT COUNT(*) FROM sales_2024) AS total, (SELECT AVG(amount) FROM sales_2024) AS avg_amount, (SELECT SUM(amount) FROM sales_2024) AS sum_amount;

场景2:递归查询(CTE独有功能)

sql

-- 组织架构树查询 WITH RECURSIVE org_tree AS ( -- 锚点:根节点 SELECT id, name, parent_id, 1 AS level FROM organization WHERE parent_id IS NULL UNION ALL -- 递归:向下遍历 SELECT o.id, o.name, o.parent_id, t.level + 1 FROM organization o INNER JOIN org_tree t ON o.parent_id = t.id ) SELECT * FROM org_tree;

场景3:复杂分页优化

sql

-- 先CTE过滤和排序,再分页 WITH ranked_data AS ( SELECT t.*, ROW_NUMBER() OVER (ORDER BY create_time DESC) AS rn FROM huge_table t WHERE status = 'ACTIVE' ) SELECT * FROM ranked_data WHERE rn BETWEEN 1 AND 100;

三、优化原理深度解析

优化机制说明适用场景
结果物化将中间结果存入临时表,避免重复计算子查询被多次引用
查询合并优化器可将CTE与外层查询合并执行计划单次引用的简单CTE
递归迭代支持树形/图形数据的遍历查询组织架构、BOM物料清单
逻辑封装将复杂逻辑拆解为多个语义清晰的步骤长SQL可维护性改造

四、Oracle优化器特殊行为

sql

-- Oracle中可控制物化行为 WITH /*+ MATERIALIZE */ cache_data AS ( -- 强制物化 SELECT * FROM large_table WHERE condition ) SELECT * FROM cache_data; WITH /*+ INLINE */ cache_data AS ( -- 强制不物化,直接合并 SELECT * FROM large_table WHERE condition ) SELECT * FROM cache_data;

Oracle优化器决策规则:

  • 默认情况下,CTE只被引用一次→ 可能不物化(直接合并)

  • CTE被引用多次→ 自动物化

  • CTE结果集很大→ 物化到临时段

  • CTE结果集很小→ 物化到内存(PGA)


五、针对您原SQL的CTE改写示例

sql

WITH base_data AS ( -- 核心关联数据:一次性获取所有基础字段 SELECT a.FLOW_NO, a.FLOW_TITLE, a.SERVICE_TYPE, a.END_TIME, a.SEND_DEPT, a.SEND_MAN, a.SEND_TIME, a.FLOW_ID, b.DISMANTLE_TYPE, b.TASK_DESC, b.START_TIME, b.REPLY_TIME, b.DEAL_TIME, b.SERVICE_TYPE_ID, b.SPECIAL_TYPE_ID, b.APP_ORDER_NUMBER, b.SERVICE_COMPANY, b.BELONG_UNIT, b.PROJECT_NAME, b.SPECIAL_TYPE, b.ISAUTO, b.JC_KH_SCORE, b.JC_KHSCORE_FEE, b.PLANTIME, b.FINISHTIME, b.DEGREE, b.PRICE, b.TOTAL, b.MONEY, b.BUDGET_DEPT, b.DUTY_DEPT, b.ISJK, b.SERVICE_COMPANY_ID FROM t_BPM_FORM_INFO a INNER JOIN T_BNS_SERVICE_BYNUM_jc b ON a.FLOW_ID = b.FLOW_ID AND a.FLOW_NO = b.APP_ORDER_NUMBER WHERE a.SEND_TIME >= TO_DATE('2021/01/01 00:00:00', 'yyyy/mm/dd hh24:mi:ss') AND a.APP_TYPE = 'netMaintain' AND a.CURRENT_STATE <> '4' AND b.SPECIAL_TYPE_ID <> '009' AND b.SERVICE_COMPANY_ID <> '2521' AND b.IS_ZH IS NULL ), -- 代维回单时间子查询(只执行1次) deal_time_info AS ( SELECT DISORDERNUMBER, TO_CHAR(MAX(CREATIONTIME), 'yyyy-mm-dd hh24:mi:ss') AS max_creation_time FROM authdb.ufp_general_info_table WHERE NODECODE = 'clz' GROUP BY DISORDERNUMBER ), -- 现场完成时间子查询 field_time_info AS ( SELECT FLOW_ID, TO_CHAR(ETIME, 'yyyy-mm-dd hh24:mi:ss') AS etime_str FROM df_task ), -- 当前环节子查询 current_step_info AS ( SELECT JOBCODE, ACTDEFNAME FROM authdb.ufp_pending_worke WHERE (JOBCODE, ACTDEFNAME) IN ( SELECT JOBCODE, MIN(ACTDEFNAME) FROM authdb.ufp_pending_worke GROUP BY JOBCODE ) ) -- 主查询:直接JOIN CTE结果 SELECT b.FLOW_NO AS 工单编号, b.FLOW_TITLE AS 工单主题, CASE WHEN b.SERVICE_TYPE IN ('室分退网', '基站退网') THEN b.DISMANTLE_TYPE ELSE '' END AS 整站拆除或整逻辑站拆除, b.TASK_DESC AS 派单描述, TO_DATE(b.START_TIME, 'yyyy/MM/dd hh24:mi:ss') AS 派单时间, TO_DATE(b.REPLY_TIME, 'yyyy/MM/dd hh24:mi:ss') AS 处理时限, COALESCE(b.DEAL_TIME, d.max_creation_time) AS 代维回单时间, CASE WHEN b.SERVICE_TYPE_ID = '14' THEN f.etime_str WHEN b.SPECIAL_TYPE_ID = '002' AND b.SERVICE_TYPE_ID = '13' THEN b.DEAL_TIME ELSE '--' END AS 现场完成时间, -- ... 其他字段 COALESCE(c.ACTDEFNAME, '已归档') AS 当前环节, CASE WHEN (b.DEAL_TIME IS NULL AND b.REPLY_TIME < TO_CHAR(SYSDATE, 'yyyy-MM-dd hh24:mi:ss') AND b.ISJK IS NULL) OR (b.DEAL_TIME IS NOT NULL AND b.REPLY_TIME < b.DEAL_TIME) THEN '是' ELSE '否' END AS 是否超时 FROM base_data b LEFT JOIN deal_time_info d ON b.APP_ORDER_NUMBER = d.DISORDERNUMBER LEFT JOIN field_time_info f ON b.APP_ORDER_NUMBER = f.FLOW_ID LEFT JOIN current_step_info c ON b.FLOW_NO = c.JOBCODE ORDER BY b.FLOW_NO;

六、性能对比总结

维度原SQL(标量子查询)CTE改写后
ufp_general_info_table扫描次数每行1次1次(全表+聚合)
df_task扫描次数每行1次1次(全表)
ufp_pending_worke扫描次数每行1次1次(全表)
适用数据量< 1000行> 10000行
可读性较低高(逻辑分层清晰)

核心结论:CTE通过空间换时间的方式,将多次重复的子查询扫描转化为单次物化+多次读取,适合子查询被频繁引用且结果集可复用的场景。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/23 1:57:30

Pixel Aurora Engine实操手册:多分辨率输出适配不同像素游戏需求

Pixel Aurora Engine实操手册&#xff1a;多分辨率输出适配不同像素游戏需求 1. 认识像素极光引擎 Pixel Aurora Engine是一款专为像素艺术创作设计的AI绘图工作站。它采用复古游戏机风格的界面设计&#xff0c;让用户仿佛在操作一台来自80年代的未来科技设备。 这个引擎的核…

作者头像 李华
网站建设 2026/5/23 1:57:32

如何快速搭建现代化管理系统:Vue3技术栈完整指南

如何快速搭建现代化管理系统&#xff1a;Vue3技术栈完整指南 【免费下载链接】vue-vben-admin A modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. Its fast! 项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin Vu…

作者头像 李华
网站建设 2026/5/23 1:57:33

【Linux复习】:基础指令/常用工具

基础指令 目录相关 pwd 打印当前所在路径ls 列出目录内容 ls # 简单列表 ls -l # 详细信息&#xff08;权限、大小、时间&#xff09; ls -a # 显示隐藏文件 ls -la # 详细 隐藏 ls -lt # 按时间排序cd 切换目录 cd /home # 绝对路径 cd .. …

作者头像 李华
网站建设 2026/5/23 1:57:43

C语言完美演绎6-17

/* 范例&#xff1a;6-17 */#include <stdio.h>#include <conio.h>int main(){int a;printf("请输入你的分数(0-100)");scanf("%d",&a);if(a>0) if(a<100) printf("你输入的分数…

作者头像 李华
网站建设 2026/5/28 12:22:18

4月2日(Harness治理工程)

AI工程的三次范式提示词工程的核心问题是怎么跟模型说话&#xff0c;让它更好地给出回答&#xff0c;可以注意我们的措施格式还可以使用少量样本示例的技巧上下文工程的核心问题变了&#xff0c;单靠提示词不够&#xff0c;需要把整个上下文窗口当做工程对象来设计。RAG检索长上…

作者头像 李华