Пусто RELIES_ON для RESULT_CACHE - PullRequest
       20

Пусто RELIES_ON для RESULT_CACHE

5 голосов
/ 29 апреля 2011

У меня есть запрос внутри функции с RESULT_CACHE.

Таким образом, когда таблица изменяется - мой кеш становится недействительным, и функция выполняется снова.

Я хочу реализовать функцию, которая зависит только от входных параметров и не зависит от каких-либо неявных зависимостей (таких как таблицы и т. Д.).

Возможно ли это (без динамического sql)?

Ответы [ 4 ]

2 голосов
/ 01 июня 2011

Если вы используете ссылку на базу данных, можно создать кэш результатов функции, который будет читать из таблицы при изменении параметра, но не будет аннулирован при изменении таблицы.

Очевидно, есть некоторые проблемы с этим подходом; производительность (даже для самостоятельной ссылки), обслуживание, функция может возвращать неверный результат, все ненавидят ссылки на базы данных и т. д.

Обратите внимание, что RELIES_ON устарела в 11gR2. Зависимости автоматически определяются во время выполнения, даже динамический SQL здесь вам не поможет. Но, очевидно, это отслеживание зависимостей не работает над ссылками базы данных.

Сценарий ниже демонстрирует, как это работает. Удалите «@myself» из функции, чтобы увидеть, как она обычно работает. Часть кода основана на этой замечательной статье .

--For testing, create a package that will hold a counter.
create or replace package counter is
    procedure reset;
    procedure increment;
    function get_counter return number;
end;
/

create or replace package body counter as
    v_counter number := 0;
    procedure reset is begin v_counter := 0; end;
    procedure increment is begin v_counter := v_counter + 1; end;
    function get_counter return number is begin return v_counter; end;
end;
/

--Create database link
create database link myself connect to <username> identified by "<password>"
using '<connect string>';

drop table test purge;
create table test(a number primary key, b varchar2(100));
insert into test values(1, 'old value1');
insert into test values(2, 'old value2');
commit;

--Cached function that references a table and keeps track of the number of executions.
drop function test_cache;
create or replace function test_cache(p_a number) return varchar2 result_cache is
    v_result varchar2(100);
begin
    counter.increment;
    select b into v_result from test@myself where a = p_a;
    return v_result;
end;
/

--Reset
begin
    counter.reset;
end;
/

--Start with 0 calls
select counter.get_counter from dual;

--First result is "value 1", is only called once no matter how many times it runs.
select test_cache(1) from dual;
select test_cache(1) from dual;
select test_cache(1) from dual;
select counter.get_counter from dual;

--Call for another parameter, counter only increments by 1.
select test_cache(2) from dual;
select test_cache(2) from dual;
select test_cache(2) from dual;
select counter.get_counter from dual;

--Now change the table.  This normally would invalidate the cache.
update test set b = 'new value1' where a = 1;
update test set b = 'new value2' where a = 2;
commit;

--Table was changed, but old values are still used.  Counter was not incremented.
select test_cache(1) from dual;
select test_cache(2) from dual;
select counter.get_counter from dual;

--The function is not dependent on the table.
SELECT ro.id           AS result_cache_id
,      ro.name         AS result_name
,      do.object_name
FROM   v$result_cache_objects    ro
,      v$result_cache_dependency rd
,      dba_objects               do
WHERE  ro.id = rd.result_id
AND    rd.object_no = do.object_id;
2 голосов
/ 29 апреля 2011

Правильный ответ НЕТ.Решение в случаях, когда такие вещи, как кэши результатов и материализованные представления, не будут работать из-за недействительности или слишком больших накладных расходов, - это опция Oracle In-Memory Database Cache.См. кэш результатов ..... как насчет сильно измененных данных Это действительно разумный вариант, а не дешевый.

2 голосов
/ 29 апреля 2011

функция, которая зависит только от ее параметров, может быть объявлена ​​DETERMINISTIC.Результаты этой функции будут кэшироваться в некоторых случаях.Этот поток на форумах OTN показывает, как результаты детерминированной функции кэшируются внутри операторов SQL.

Начиная с 10gR2, результаты функции не кэшируются между операторами SQL и не кэшируютсяPL / SQL.Тем не менее, эта функция кэширования может быть полезна, если вы вызываете функцию в SELECT, где она может вызываться много раз.

У меня сейчас нет экземпляра 11gR2, поэтому я не могу протестироватьФункция RESULT_CACHE, но рассматривали ли вы возможность отказа от функции, полагаясь на фиксированную фиктивную таблицу (например, таблицу, которая никогда не обновляется)?

1 голос
/ 29 апреля 2011

Два варианта:

  1. Не запрашивать таблицы.

  2. Реализация собственного кэша - оберните функцию в пакет и сохраните результаты запроса в таблице PL / SQL в памяти. Недостатком этого подхода, однако, является то, что кэш работает только в течение одного сеанса. Каждый сеанс будет поддерживать свой собственный кэш.

...