result_cache函数必须是确定性的,即相同输入永远返回相同输出、不依赖会话状态或数据库变化;需显式声明deterministic,禁用sysdate、user、dml、自治事务;查表须加/+ result_cache /提示;参数类型长度严格匹配,缓存键由字节级参数值生成;底层表任意dml即触发全量失效;命中需通过v$result_cache_objects和10046 trace双重验证。
result_cache函数必须是确定性的
oracle的result_cache机制只允许缓存「确定性」函数的结果,即相同输入永远返回相同输出、且不依赖会话状态或数据库变化。如果你的函数里调用了sysdate、user、查询表(未加result_cache hint)、或修改了包变量,oracle会在编译时报错:pls-00999: result-cached function must be pure。
实操建议:
- 用
DETERMINISTIC关键字显式声明函数——这是强制要求,不是可选项 - 避免在函数体内执行DML、DDL、自治事务(
AUTONOMOUS_TRANSACTION) - 若需查表,确保该表极少更新,且查询语句本身也加了
/*+ RESULT_CACHE */hint(仅适用于SELECT) - 测试时可用
SELECT * FROM V$RESULT_CACHE_OBJECTS确认缓存是否命中
参数类型和大小直接影响缓存键生成
Oracle把函数所有输入参数的值拼接成一个内部缓存键(cache key),任何参数类型不支持隐式转换、或长度超限,都会导致缓存失效或无法存入。
常见问题:
-
VARCHAR2参数实际传入长度接近4000字节时,可能触发缓存拒绝(报ORA-0600 [qesrcGetKey:1]类错误) -
DATE参数带时区(TIMESTAMP WITH TIME ZONE)不被支持,会编译失败 - 对象类型(
OBJECT、VARRAY)作为参数时,必须定义为FINAL且含MAP方法,否则缓存键无法计算 - 推荐统一用
VARCHAR2(4000)、NUMBER、DATE等基础类型,避免复杂结构体
缓存生命周期不由函数控制,而由底层数据变更自动失效
RESULT_CACHE不是手动管理的内存池,它依赖Oracle对「函数所依赖对象」的变更感知。只要函数体里直接/间接引用的表、视图、序列发生DML(哪怕只是INSERT一条记录),整个函数的所有缓存条目立刻失效。
这意味着:
- 不要指望缓存长期存在——高写入表上的函数缓存命中新率可能极低
- 不能用
DBMS_RESULT_CACHE包手动清除某函数的缓存(只能清空全部或按ID删,ID不可预测) - 若函数依赖多个表,其中一个表频繁更新,其余表的稳定性就失去意义
- 可通过
V$RESULT_CACHE_DEPENDENCY查函数与对象的依赖关系,提前评估失效风险
启用前务必验证执行计划是否真走缓存路径
即使函数成功创建并标了RESULT_CACHE,也不代表每次调用都走缓存。Oracle会在解析阶段决定是否启用缓存逻辑,受RESULT_CACHE_MODE初始化参数(MANUAL或FORCE)和会话级设置影响。
检查方式:
- 开启SQL trace后查看10046事件,命中缓存时会出现
result cache hit字样 - 执行
EXPLAIN PLAN FOR SELECT your_func(...) FROM DUAL,再查PLAN_TABLE,若出现RESULT CACHE操作符,说明路径已启用 - 注意:绑定变量值不同会导致缓存键不同,硬编码字面量(如
your_func('ABC'))比your_func(:b1)更容易复用缓存
缓存效果高度依赖输入分布和底层数据稳定性,上线前一定要用真实业务参数压测,而不是只看单次执行时间。











