You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle环境下SQL Delete语句执行过慢(无记录仍耗时)求助

SQL删除语句优化方案

先修正核心逻辑错误

原SQL里的OR条件没有加括号,由于AND优先级高于OR,实际执行逻辑会偏离预期,变成:
(ud2.udt02_id=ctree.charge_cd AND mo.s_mo_status_cd in ('L','C') AND mo.complt_dt <= SYSDATE -7) OR mo.allow_timesheet_fl='N'
这会导致大量无关的mo_hdr记录被关联,必须把OR的过滤逻辑用括号包裹,确保符合业务需求:

AND (
    (mo.s_mo_status_cd IN ('L','C') AND mo.complt_dt <= SYSDATE -7)
    OR mo.allow_timesheet_fl = 'N'
)

优化关联条件(性能瓶颈核心)

你推测的concat(mo.bld_proj_id,'%') like ud2.udt02_name确实是性能短板:

  • 这种反向模糊匹配(判断ud2.udt02_name是否以mo.bld_proj_id开头)会让数据库无法使用ud2.udt02_name上的索引,只能全表扫描,数据量大时耗时极长。
  • 改用Oracle原生字符串拼接符||,写法更规范,同时如果ud2.udt02_name有前缀索引,有机会命中索引:
ON ud2.udt02_name LIKE mo.bld_proj_id || '%'

改写删除语句,提升执行效率

原SQL用IN子查询的方式,在数据量大时性能不如EXISTS或直接JOIN,推荐两种改写方式:

方式1:用EXISTS替代IN

DELETE FROM tc_0002.charge_branch_charge@etime ctree
WHERE EXISTS (
    SELECT 1
    FROM tc_0002.udt02@etime ud2
    INNER JOIN deltek.mo_hdr mo
        ON ud2.udt02_name LIKE mo.bld_proj_id || '%'
    WHERE ud2.udt02_id = ctree.charge_cd
      AND (
          (mo.s_mo_status_cd IN ('L','C') AND mo.complt_dt <= SYSDATE -7)
          OR mo.allow_timesheet_fl = 'N'
      )
);

方式2:用JOIN直接关联删除(Oracle 12c+支持)

DELETE ctree
FROM tc_0002.charge_branch_charge@etime ctree
JOIN tc_0002.udt02@etime ud2 ON ud2.udt02_id = ctree.charge_cd
JOIN deltek.mo_hdr mo ON ud2.udt02_name LIKE mo.bld_proj_id || '%'
WHERE (
    (mo.s_mo_status_cd IN ('L','C') AND mo.complt_dt <= SYSDATE -7)
    OR mo.allow_timesheet_fl = 'N'
);

添加必要索引,彻底解决慢查询

给以下字段创建索引,让数据库快速定位关联数据:

  1. 给udt02表建组合索引,覆盖关联和查询字段:
CREATE INDEX idx_udt02_name_id ON tc_0002.udt02(udt02_name, udt02_id);
  1. 给mo_hdr表建组合索引,覆盖过滤和关联字段:
CREATE INDEX idx_mo_bld_status_dt_fl ON deltek.mo_hdr(bld_proj_id, s_mo_status_cd, complt_dt, allow_timesheet_fl);
  1. 确保charge_branch_charge表的charge_cd字段有索引(如果是主键则无需额外创建)。

可选:分批删除避免资源占用

如果待删记录数量巨大,一次性删除会消耗大量undo日志,导致执行缓慢,可采用分批删除的方式:

DECLARE
    v_rows_deleted NUMBER := 1;
BEGIN
    WHILE v_rows_deleted > 0 LOOP
        DELETE FROM tc_0002.charge_branch_charge@etime ctree
        WHERE EXISTS (
            SELECT 1
            FROM tc_0002.udt02@etime ud2
            INNER JOIN deltek.mo_hdr mo
                ON ud2.udt02_name LIKE mo.bld_proj_id || '%'
            WHERE ud2.udt02_id = ctree.charge_cd
              AND (
                  (mo.s_mo_status_cd IN ('L','C') AND mo.complt_dt <= SYSDATE -7)
                  OR mo.allow_timesheet_fl = 'N'
              )
        ) AND ROWNUM <= 1000; -- 每次删除1000条,可根据实际调整
        
        v_rows_deleted := SQL%ROWCOUNT;
        COMMIT;
    END LOOP;
END;
/

内容的提问来源于stack exchange,提问作者Mimi9864

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 18:55:13