问题描述
是否有方法强制任何查询的结果缓存,并让应用程序处理无效?
在极端情况下(不太明智) ,请执行以下操作:
从dba_tables中选择/*+ force_result_cache */ * ,其中table ='XXX';
基本上,我们希望缓存复杂的查询(涉及多级视图、sysdate、'按级连接<= x'行生成器等)并在必要时让应用程序失效。结果缓存具有我们所需的基本功能: DB截取查询、比较绑定、返回预查询结果的能力。但它对缓存的内容限制太大,而且即使是显式重写,也不允许对陈旧数据进行任何容忍。当然,我理解其中的原因,而且它们完全合情合理,我只是在尝试将其应用扩展到我的应用程序中。
目前,我们有自己的缓存,使用类似于就地MV的东西。这样做很有效,但我们必须1)进行完全刷新,这非常耗时; 2)由于视图-视图依赖关系,因此必须按特定的顺序进行刷新。
如有任何建议或备选办法,将不胜感激。谢谢你抽出时间。
我不明白您所说的“让应用程序处理无效”是什么意思。结果缓存完全由Oracle数据库管理。
第一次执行查询时, Oracle会将结果存储在高速缓存中。如果表中的数据发生更改,则会立即使缓存失效。
比如。我创建了一个函数,它休眠1秒以使增益清晰,并创建了一个包含10行的表:
第一次执行计数5行需要5秒。第二个接近0 :
但是,只要您向t添加另一行, Oracle就会使缓存失效。并且该查询再次占用5秒:
所以你不能“让应用程序来管理它”,这使得它不适合对包含大量DML的表进行查询。
如果您正在寻找一种方法来拥有一个过时的数据缓存,那么MV就是最好的方法。在复杂的查询上创建MV ,并将其设置为按计划进行刷新。然后你就可以把你的应用指向MV了。
或者,您可以更改以下选项的查询/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/
然后, Oracle可以自动使用查询重写到陈旧MV并从该MV返回数据:
https://www.youtube.com/watch?v=2iRadmXtMGk
https://www.youtube.com/watch?v=aSj9eDDUE-Y
FWIW ,您可以对会话中的所有语句强制进行结果缓存,其中:
然后,使用no_result_cache提示对特定查询禁用它:
在极端情况下(不太明智) ,请执行以下操作:
从dba_tables中选择/*+ force_result_cache */ * ,其中table ='XXX';
基本上,我们希望缓存复杂的查询(涉及多级视图、sysdate、'按级连接<= x'行生成器等)并在必要时让应用程序失效。结果缓存具有我们所需的基本功能: DB截取查询、比较绑定、返回预查询结果的能力。但它对缓存的内容限制太大,而且即使是显式重写,也不允许对陈旧数据进行任何容忍。当然,我理解其中的原因,而且它们完全合情合理,我只是在尝试将其应用扩展到我的应用程序中。
目前,我们有自己的缓存,使用类似于就地MV的东西。这样做很有效,但我们必须1)进行完全刷新,这非常耗时; 2)由于视图-视图依赖关系,因此必须按特定的顺序进行刷新。
如有任何建议或备选办法,将不胜感激。谢谢你抽出时间。
我不明白您所说的“让应用程序处理无效”是什么意思。结果缓存完全由Oracle数据库管理。
第一次执行查询时, Oracle会将结果存储在高速缓存中。如果表中的数据发生更改,则会立即使缓存失效。
比如。我创建了一个函数,它休眠1秒以使增益清晰,并创建了一个包含10行的表:
create or replace function f (p int) return int as begin dbms_lock.sleep(1); return p; create table t ( x int insert into t select rownum from dual connect by level <= 10; commit;
第一次执行计数5行需要5秒。第二个接近0 :
SQL> set timing on SQL> select /*+ result_cache */count(f(x)) from t 2 where x <= 5; COUNT(F(X)) ----------- Elapsed: 00:00:05.52 SQL> select /*+ result_cache */count(f(x)) from t 2 where x <= 5; COUNT(F(X)) ----------- Elapsed: 00:00:00.47
但是,只要您向t添加另一行, Oracle就会使缓存失效。并且该查询再次占用5秒:
SQL> insert into t values (11); 1 row created. Elapsed: 00:00:00.31 SQL> commit; Commit complete. Elapsed: 00:00:00.31 SQL> select /*+ result_cache */count(f(x)) from t 2 where x <= 5; COUNT(F(X)) ----------- Elapsed: 00:00:05.46
所以你不能“让应用程序来管理它”,这使得它不适合对包含大量DML的表进行查询。
如果您正在寻找一种方法来拥有一个过时的数据缓存,那么MV就是最好的方法。在复杂的查询上创建MV ,并将其设置为按计划进行刷新。然后你就可以把你的应用指向MV了。
或者,您可以更改以下选项的查询/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/修改/
alter session set query_rewrite_integrity = stale_tolerated;
然后, Oracle可以自动使用查询重写到陈旧MV并从该MV返回数据:
https://www.youtube.com/watch?v=2iRadmXtMGk
https://www.youtube.com/watch?v=aSj9eDDUE-Y
FWIW ,您可以对会话中的所有语句强制进行结果缓存,其中:
alter session set result_cache_mode = force;
然后,使用no_result_cache提示对特定查询禁用它:
SQL> alter session set result_cache_mode = force; Session altered. Elapsed: 00:00:00.40 SQL> select count(f(x)) from t 2 where x <= 5; COUNT(F(X)) ----------- Elapsed: 00:00:00.47 SQL> select /*+ no_result_cache */count(f(x)) from t 2 where x <= 5; COUNT(F(X)) -----------