跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

如何实现PL/SQL函数的缓存_RESULT_CACHE提升重复查询性能

RESULT_CACHE未生效主要因三处硬性限制:一是函数内含非确定性操作(如SYSDATE、触发器表等);二是参数非标量类型或调用非DETERMINISTIC函数;三是缓存键对类型/精度敏感,隐式转换导致键不匹配。 RESULT_CACHE 为什么没生效?检查这三处硬性限制 pl/sql 函数加了
result_cache
却没走缓存,大概率是撞上了 oracle 的强制约束。它不是“加了就缓”——函数体内不能出现任何会破坏确定性的操作。
SELECT
语句必须只查
DETERMINISTIC
表(即无触发器、无物化视图日志、不涉及
SYSDATE
/
USER
/
DBMS_RANDOM
等非确定性函数) 函数参数类型必须是标量(
VARCHAR2
、
NUMBER
、
DATE
),不能是
REF CURSOR
、
RECORD
或对象类型 函数体里不能调用任何非
DETERMINISTIC
函数,包括你自己写的没加
DETERMINISTIC
关键字的函数 怎么验证缓存是否真的命中?别信执行计划 执行计划里看不到
RESULT_CACHE
是否起效,得靠实际运行时行为和系统视图交叉验证。 第一次调用后查
V$RESULT_CACHE_OBJECTS
:有对应条目且
STATUS = 'Published'
才算缓存成功 连续两次相同参数调用,看
V$SQL
中对应 SQL 的
EXECUTIONS
增长是否为 1(第二次应跳过 SQL 执行) 在函数里加
DBMS_OUTPUT.PUT_LINE('executed')
—— 如果第二次还打印,说明根本没走缓存,立刻回头检查上一条的限制项 RESULT_CACHE 和函数参数绑定太敏感,小心隐式转换 缓存键(cache key)是按参数值的**字节级表示**生成的,哪怕语义相同,类型或精度不同就会分两个缓存槽。 传入
NUMBER(10)
和
NUMBER(10,0)
被视为不同键
'123'
(
VARCHAR2
)和
123
(
NUMBER
)绝对不共享缓存 调用方用绑定变量传参时,确保变量声明类型与函数参数完全一致,别依赖 PL/SQL 自动转换 示例:函数定义为
FUNCTION get_name(p_id IN NUMBER) RETURN VARCHAR2 RESULT_CACHE
,调用时用
get_name(123)
和
get_name(TO_NUMBER('123'))
是安全的;但用
get_name('123')
就会失败(类型不匹配,报
ORA-06553: PLS-306
)。 缓存失效比你想的更频繁,尤其在 DML 后
RESULT_CACHE
不是独立内存池,它和底层表强耦合。只要函数里查的任意一张表发生 DML(哪怕只是另一会话做的
INSERT
),整个函数的所有缓存项立刻失效。 没有细粒度失效机制——改一行,全刷掉 如果函数查多张表,其中一张被 DML,全部缓存清空 高并发写场景下,缓存命中率可能趋近于 0,这时不如关掉,避免额外的哈希键计算开销 真正适合
RESULT_CACHE
的函数,是那些背后查的是极少变动的配置表、码表,或者纯计算型(无 SQL)函数。业务主表上的查询,基本别指望它稳住。

相关文章