1. SQL性能优化实战:标量子查询陷阱与改写方案
最近在数据库巡检过程中,我发现了一条典型的性能问题SQL。这条SQL在TOP SQL CPU和TOP SQL LOGICAL两个监控项中都排名第一,引起了我的高度关注。通过sql10.sql脚本收集相关性能数据后,我确认这是一个典型的标量子查询性能问题案例。由于这条SQL是核心业务中的关键查询,执行频率极高,导致逻辑读飙升,CPU使用率也随之增加。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题SQL分析
2.1 原始SQL业务场景
这条SQL涉及两个主要表:
- 主表:ORDER_DETAIL(订单明细表),存储订单的基本信息
- 关联表:ORDER_EXECUTION@DB_LINK(订单执行记录表),通过数据库链接访问,记录每个订单的执行情况
业务需求是查询未完全执行的订单信息,包括:
- 订单基本信息:客户姓名、部门编码、工位号等
- 执行情况统计:每个订单的完成数量和剩余数量
- 过滤条件:只显示完成数小于订单数量的订单
2.2 原始SQL性能问题
原始SQL使用了多个标量子查询来计算完成数和剩余数。这种写法存在严重性能问题:
sql复制SELECT
CUSTOMER_NAME 客户姓名,
(SELECT count(*) FROM ORDER_EXECUTION@DB_LINK c
WHERE c.ORDER_NO=A.ORDER_NO AND c.DELETE_FLAG='0') 完成数,
a.QUANTITY - (SELECT count(*) FROM ORDER_EXECUTION@DB_LINK c
WHERE c.ORDER_NO=A.ORDER_NO AND c.DELETE_FLAG='0') 剩余数
FROM ORDER_DETAIL A
2.3 问题根源分析
-
标量子查询的逐行执行问题:
标量子查询会对主查询返回的每一行都执行一次。如果主查询返回1000行,子查询就要执行2000次(完成数和剩余数各计算一次) -
重复计算问题:
相同的子查询逻辑被重复执行两次,违反了DRY原则 -
复杂过滤条件:
使用了嵌套的NOT IN子
