2013-06-10 2 views
1

У меня есть два пользовательских типов в моей БД OracleOracle кэширует CLOB к временной таблице

TYPE SETTING IS OBJECT (
    SETT_NAME VARCHAR2(32767), 
    SETT_VALUE CLOB, 
); 

TYPE SETTINGS_SET IS TABLE OF SETTING; 

И у меня есть простая функция, которая возвращает SETTINGS_SET

FUNCTION Revision RETURN SETTINGS_SET PIPELINED IS 
    INSTANCE SETTING; 
BEGIN 
-- body is simplified for example 
    INSTANCE = SETTING('Id', 'Long clob value'); 
    PIPE ROW(INSTANCE); 
END;  

или не конвейерную функцию

FUNCTION Revision RETURN SETTINGS_SET IS 
    SET SETTINGS_SET = SETTINGS_SET(); 
BEGIN 
-- body is simplified for example 
    SETTINGS_SET(1) := SETTING('Id', 'Long clob value'); 
END; 

И это хорошо работает, но оракул кэширует значение CLOB для временного хранения для текущего сеанса.
Это хранилище можно найти в системном столе v$session.

Моя проблема заключается в том, что у меня в моем приложении только один сеанс Oracle, и это хранилище быстро заполняется.

1) Почему оракулы скрываются в этом случае?
2) Можно ли отключить кеширование значений CLOB в моей функции?
Также я пробовал функцию не-трубопроводов, но rhis не помог.

+0

Если вам нужно пройдите вокруг большого количества данных, тогда вам понадобятся большие объемы памяти, бот h диском и оперативной памятью. Разве вы не можете открыть вторую сессию? Кажется, что немного на маленькой стороне. – Ben

+0

слишком занят, чтобы создать пример atm, но попробуйте dbms_lob.freetemporary (your_clob) после строки строки. По умолчанию temp clobs будет очищать (в конечном итоге), когда выходит из области видимости, что может занять много времени в зависимости от того, сколько строк вы используете здесь. – tbone

+0

@tbone У меня есть исключение «ORA-22275: недопустимый локатор больших объектов», потому что я не создаю CLOB с 'dbms_lob.createtemporary' – Ilya

ответ

2

Поскольку вы прокладываете выходные данные, вам нужно очистить временные складки на конце пользователя. Это означает, что вы создаете указатель внутри функции и передаете его (завершите его) конечным пользователем, которому нужно будет очистить. Например:

CREATE OR REPLACE 
type MY_CLOB as object 
(
    some_char varchar2(4000), 
    some_clob clob 
); 

CREATE OR REPLACE 
type MY_CLOB_TAB as table of my_clob; 

Функция:

CREATE OR REPLACE function pipe_clobs 
return my_clob_tab 
pipelined IS 
    l_clob_obj my_clob; 
    l_clob CLOB; 
BEGIN 

    for i in 1 .. 10 
    loop 
    l_clob := 'This is temp clob ' || i; 
    l_clob_obj := my_clob('My varchar2 value', l_clob); 
    pipe row(l_clob_obj); 
    end loop; 

END; 

И пользователь будет (например):

begin 
    for rec in (select some_char, some_clob from table(pipe_clobs)) 
    loop 
     -- use it 
     dbms_output.put_line('Clob value is: ' || rec.some_clob); 
     -- and free it 
     dbms_lob.freetemporary(rec.some_clob); 
    end loop; 
end; 

Проверка через:

select * from v$temporary_lobs; 
+0

Thx, ваш ответ помог мне обнаружить утечку памяти. Спасибо – Ilya

Смежные вопросы