添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 强制不可缓存的查询的结果缓存?

askTom 2016-12-13
1290

问题描述

是否有方法强制任何查询的结果缓存,并让应用程序处理无效?

在极端情况下(不太明智) ,请执行以下操作:

从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))
-----------