从其他表更新列:我的SQL查询是否正确?为何执行缓慢?
问题分析与优化方案
1. 原SQL的语法错误
你的exists子句存在别名引用错误:子查询里的表别名是c,但你写的是A.CRMCA = B.CUST_ID,应该改为C.CRMCA = B.CUST_ID,否则会直接报错。
2. 性能瓶颈根源
- 重复扫描大表:原SQL会两次扫描1000万行的
CMF_ACC_EXT_LEGACY,一次是更新子查询,一次是exists判断,双重全表扫描直接拉高耗时。 - 无规则的
rownum=1:子查询仅用rownum=1但未指定排序逻辑,返回的ES_FLAG是随机值,逻辑可能不符合业务预期。 - 缺失索引:如果
CMF_ACC_EXT_LEGACY.CRMCA和CP_RAJU.CUST_ID没有索引,关联时会触发全表扫描+嵌套循环,效率极低。
3. 优化后的SQL写法
写法一:用MERGE语句(Oracle推荐批量更新方案)
MERGE只需扫描一次大表,效率远高于原写法:
MERGE INTO CP_RAJU b USING ( SELECT CRMCA, ES_FLAG FROM ( SELECT CRMCA, ES_FLAG, -- 建议替换ORDER BY 1为实际业务字段,比如主键,确保取值固定 ROW_NUMBER() OVER(PARTITION BY CRMCA ORDER BY 1) rn FROM CMF_ACC_EXT_LEGACY ) WHERE rn = 1 ) a ON (a.CRMCA = b.CUST_ID) WHEN MATCHED THEN UPDATE SET b.ES_FLAG = a.ES_FLAG;
写法二:关联子查询更新(避免重复扫描)
如果不想用MERGE,也可以改成单次关联的更新逻辑:
UPDATE ( SELECT b.ES_FLAG AS target_flag, a.ES_FLAG AS source_flag FROM CP_RAJU b JOIN ( SELECT CRMCA, ES_FLAG, ROW_NUMBER() OVER(PARTITION BY CRMCA ORDER BY 1) rn FROM CMF_ACC_EXT_LEGACY ) a ON a.CRMCA = b.CUST_ID WHERE a.rn = 1 ) SET target_flag = source_flag;
4. 额外性能优化建议
- 给
CMF_ACC_EXT_LEGACY建立覆盖索引:CREATE INDEX IDX_CMF_CRMCA_ES ON CMF_ACC_EXT_LEGACY(CRMCA) INCLUDE(ES_FLAG); - 给
CP_RAJU.CUST_ID建立索引,加快匹配速度:CREATE INDEX IDX_CP_CUST_ID ON CP_RAJU(CUST_ID); - 明确排序逻辑:如果
CMF_ACC_EXT_LEGACY中同一CRMCA对应多条记录,把ORDER BY 1替换为实际业务字段(比如主键),避免随机取值。
内容的提问来源于stack exchange,提问作者Aman
相关产品推荐
相关产品推荐

