ITPub博客

首页 > 数据库 > Oracle > Oracle大in慢查询优化

Oracle大in慢查询优化

原创 Oracle 作者:tompson666 时间:2025-08-23 10:59:32 0 删除 编辑

1、某客户业务模块大in导致慢SQL:

2.从现场获取到慢SQL信息:

1)表数据量不大,只有几十万

2)表更新较为频繁,从另外系统同步过来,实际上变更并不频繁,只有少量的updates

3.AWR报告无明显异常:

4.业务逻辑分析:

1)原始SQL:

SELECT A.FId "id", A.fnumber "number", A.fctrlstrategy "ctrlStrategy", A.fmasterid "masterid", A.fstatus "status", A.fcreateorgid "createOrg.id"FROM xx_Material A WHERE A.FId IN (SELECT COLUMN_VALUE FROM UDT_INTTABLE(?)) AND (A.fbitindex IN (SELECT COLUMN_VALUE FROM UDT_INTTABLE(?)) OR (A.fcreateorgid = ? AND A.fctrlstrategy = ? OR A.fstatus = ? AND A.fctrlstrategy = ?) OR A.fctrlstrategy = ? AND (A.fcreateorgid = ? OR A.fstatus = ? AND A.fcreateorgid=100000))


2)SQL分析

UDT_INTTABLE是一个自定义类型,用于封装大in,规避Oracle in超过1000报错问题,涉及代码:

        CREATE OR REPLACE TYPE "UDT_INTTABLE" AS TABLE OF number(19)

使用IN (SELECT COLUMN_VALUE FROM UDT_INTTABLE(?)) 将大量in封装后,整个执行计划为FTS(未截图)


5.执行计划分析:

由于FID是主键,整个表几十W记录,而in只有上千个,从COST成本预估分析,正确的执行计划应该使用in..list(iterator) NL ,类似如下:

optimizer预计计算有误,执行计划FTS有问题


5.优化方案:

1)考虑使用table函数代替子查询( SELECT COLUMN_VALUE FROM UDT_INTTABLE(?))改写,如:

select * from t_big where id in (select * from table(UDT_INTTABLE(1,2,3,4,5,6,7,8,9,10,100))),执行计划如上。


2)将in转换为临时表(依赖程序框架实现),in list iterator转换为NL JOIN




来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70038077/viewspace-3094085/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle ACE PostgreSQL ACE PG/MySQL内核技术推广者 著有《Oracle高性能自动化运维》 目前致力于Oracle/MySQL/PG技术推广&信创项目交付&最佳实践探索。公众号:dba悠然

注册时间:2024-04-14

  • 博文量
    42
  • 访问量
    33722