oracle 21c 存储过程性能瓶颈主因是sql写法与参数处理不当,需严格使用json类型声明参数、避免or+is null条件、慎用动态对象名和like '%xxx%',优先采用sql宏而非execute immediate。

参数类型必须严格匹配,别用 VARCHAR2 传 JSON
声明参数时用 VARCHAR2 或 CLOB 接收 JSON 字符串,会导致 JSON_EXISTS 总返回 FALSE、JSON_VALUE 总返回 NULL——Oracle 不会自动解析,也不报错,只是静默当普通字符串处理。
必须声明为 JSON 类型:json_input JSON。否则所有 JSON 函数都退化为字符串操作,索引失效、路径校验绕过、性能下降明显。
WHERE 条件别堆 OR + IS NULL,用宏或 CASE 控制开关
常见错误是写成:WHERE (p_status IS NULL OR status = p_status) AND (p_date_from IS NULL OR created_date >= p_date_from)。这种写法让优化器无法有效选择索引,尤其当多个参数可空时,执行计划极易退化为全表扫描。
更稳妥的做法:
• 多个独立 SQL 宏(如 filter_by_status、filter_by_date)各自返回完整条件或空字符串
• 主查询用 AND (1=1 OR &&filter_by_status('SHIPPED')) 包裹,确保语法合法且展开后仍是静态语句
• 所有对象名(表、列)必须写死,宏只接受标量参数
别在存储过程中拼接表名或列名
SQL 宏不是动态 SQL,不支持运行时替换对象名。试图用 p_table_name 参数控制查询表,会直接报 ORA-64625: invalid identifier in sql macro。
如果真需要跨表操作:
• 先查 ALL_TABLES 或 USER_TAB_COLUMNS 做白名单校验
• 用 EXECUTE IMMEDIATE + DBMS_ASSERT.SQL_OBJECT_NAME 防注入
• 但应尽量避免——它破坏执行计划复用,且无法被 EXPLAIN PLAN 静态分析
大数据量筛选慎用 LIKE '%xxx%' 参数
哪怕加了索引,LIKE '%abc' 也必然跳过索引走全表扫描。如果业务允许,优先改用全文索引(CTXSYS.CONTEXT)或函数索引(如 UPPER(name));如果必须模糊前缀,至少限制为 LIKE 'abc%' 并确保字段上有对应前导索引。
另外注意:
• IN 列表超过 1000 项会报错,需拆分或改用临时表
• NOT IN 遇到 NULL 会整个条件失效,改用 NOT EXISTS
EXPLAIN PLAN 能看到完整路径,绑定变量机制依然生效。而一旦混用 EXECUTE IMMEDIATE 和宏,就失去这个优势——两者不能共存于同一过滤逻辑中。











