暂无图片
暂无图片
1
暂无图片
暂无图片
1
暂无图片

【ORACLE】21c版本新特性之增强的函数结果缓存功能

前言

参考官方文档:https://docs.oracle.com/en/database/oracle/oracle-database/21/lnpls/plsql-subprograms.html#GUID-250BDBBB-0CD6-4D56-9DDF-6FCEDC110D00

在21c版本之前,oracle已经有了函数结果缓存功能,但这次新增了 语句块列表、PL/SQL 函数历史跟踪、对象块列表以及允许结果缓存到磁盘

为函数启用结果缓存

官方给了个例子,但我觉得不够明显,所以稍微改了下

sqlplus / as sysdba alter session set container=xepdb1; --授权dbms_lock包,下面要用到 grant execute on dbms_lock to hr; --切换到hr conn hr/hr2021@modb:1521/xepdb1 --创建包含有结果缓存函数的包 CREATE OR REPLACE PACKAGE department_pkg AUTHID DEFINER IS TYPE dept_info_record IS RECORD ( dept_name departments.department_name%TYPE, mgr_name employees.last_name%TYPE, dept_size PLS_INTEGER ); -- Function declaration FUNCTION get_dept_info (dept_id NUMBER) RETURN dept_info_record RESULT_CACHE; END department_pkg; / CREATE OR REPLACE PACKAGE BODY department_pkg IS -- Function definition FUNCTION get_dept_info (dept_id NUMBER) RETURN dept_info_record RESULT_CACHE IS rec dept_info_record; BEGIN SELECT department_name INTO rec.dept_name FROM departments WHERE department_id = dept_id; SELECT e.last_name INTO rec.mgr_name FROM departments d, employees e WHERE d.department_id = dept_id AND d.manager_id = e.employee_id; SELECT COUNT(*) INTO rec.dept_size FROM EMPLOYEES WHERE department_id = dept_id; sys.dbms_lock.sleep(5);--延时5秒 RETURN rec; END get_dept_info; END department_pkg; /
复制

函数结果缓存的写法就是在函数声明后加上 “RESULT_CACHE”,另外,这个例子中,我加入了一个延时5秒,目的是模拟复杂逻辑下执行代码速度过慢的问题,然后再调用函数看效果

declare rec department_pkg.dept_info_record; begin rec:=department_pkg.get_dept_info(10); end; / declare rec department_pkg.dept_info_record; begin rec:=department_pkg.get_dept_info(10); end; / declare d_name varchar2(100); begin d_name:=department_pkg.get_dept_info(10).dept_name; end; /
复制

可以看到,第一次执行第一段,需要5秒钟;
然后再执行一次,则马上完成;
第三段是获取函数返回type中的一个值,也是马上返回。
如果你切换另一个会话,再执行这个函数,也是马上返回。

用同样的参数多次调用这个函数,则不再需要经过一次重复又复杂的逻辑进行计算,而是直接用第一次缓存的结果进行返回,且不受限于不同会话及内存大小。当数据源中的任意一个数据发生变化,缓存就会失效,所以此功能应该应用于源数据不经常修改的场景。

结果缓存递归函数

以计算斐波拉契数列中的值为例,这个数列从第3项开始,每一项都等于前两项之和,如下
0,1,1,2,3,5,8…
假设我们定义第3项为第1项,则可以创建如下函数,用来计算第几项分别是几

CREATE OR REPLACE FUNCTION fibonacci (n NUMBER) RETURN NUMBER RESULT_CACHE AUTHID DEFINER IS BEGIN IF (n =0) OR (n =1) THEN RETURN 1; ELSE RETURN fibonacci(n - 1) + fibonacci(n - 2); END IF; END; /
复制

如果计算fibonacci(7),则函数中需要再计算fibonacci(6)和fibonacci(5),继续迭代进去,计算fibonacci(6)的时候,则函数中需要再计算fibonacci(5)和fibonacci(4),你会发现fibonacci(5)重复了,此时这个函数结果缓存功能就派上用场了,它可以使用之前计算的值,马上返回对应的结果,大大加快了计算效率。这种特性对于机器学习中大量的重复计算是很有帮助的。

结果缓存的管理

缓存的结果存储在系统全局区域 (SGA) 中。
函数结果缓存 与 结果缓存 共享一套管理基础表及管理方式。

ORACLE提供了两个视图可以查看目前结果缓存使用的情况:

select * from GV$RESULT_CACHE_OBJECTS; select * from GV$RESULT_CACHE_STATISTICS;
复制

RAC模式下,优先访问本地的缓存,如果本地不存在,则可能从另一个节点的本地缓存中读取。数据库会根据V$RESULT_CACHE_OBJECTS.GLOBAL的值和V$RESULT_CACHE_STATISTICS中的"Global Prune Count"、"Global Prune By Self Count"来判断应该如何获取缓存。
https://docs.oracle.com/en/database/oracle/oracle-database/21/lnpls/plsql-subprograms.html#GUID-8F7227E9-4388-4A64-9D1C-5F134A3022F2

--缓存结果 select * from GV$RESULT_CACHE_OBJECT where TYPE='Result' ; --缓存依赖对象 select * from GV$RESULT_CACHE_OBJECT.TYPE='Dependency'; --禁用某个缓存(缓存黑名单) select cache_id from GV$RESULT_CACHE_OBJECT where type='Result' and name like '%FIBONACCI%'; begin DBMS_RESULT_CACHE.Black_List_Add (cache_id=>'4hstsfjcfpu3g0b0n4jpsszm48'); end; / --移除缓存黑名单 begin DBMS_RESULT_CACHE.Black_List_Remove(cache_id=>'4hstsfjcfpu3g0b0n4jpsszm48'); end; / --清空缓存黑名单 begin DBMS_RESULT_CACHE.Black_List_Clear; end; / --查询缓存黑名单 select * from table (DBMS_RESULT_CACHE.Black_List);
复制

具体参考 https://docs.oracle.com/en/database/oracle/oracle-database/21/arpls/DBMS_RESULT_CACHE.html 以了解更多关于DBMS_RESULT_CACHE的用法

热修补PLSQL

如果修改了plsql对象,比如某个函数,而且这个函数是结果缓存函数的依赖对象,则函数缓存结果可能不会刷新,需要按如下步骤以避免此种情况的发生

  1. 将结果缓存置于旁路模式并刷新现有结果:
BEGIN DBMS_RESULT_CACHE.Bypass(TRUE); DBMS_RESULT_CACHE.Flush; END; / --在RAC环境中,这一步每个节点都要执行
复制
  1. 打PLSQL补丁.
  2. 继续使用结果缓存:
BEGIN DBMS_RESULT_CACHE.Bypass(FALSE); END; / --在RAC环境中,这一步每个节点都要执行
复制
最后修改时间:2021-12-30 21:26:32
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
1人已赞赏
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

墨天轮福利君
暂无图片
3年前
评论
暂无图片 0
您好,您的文章已入选合格奖,10墨值奖励已经到账请查收! ❤️我们还会实时派发您的流量收益。
3年前
暂无图片 点赞
评论