Почему использование функции REPLACE для CLOB приводит к увеличению CACHE_LOBS?

У меня есть требование использовать встроенную функцию REPLACE для переменной CLOB как часть более крупного процесса PL/SQL. Я использую Oracle 11g R2, и функция работает нормально, поскольку она выполняет замену по мере необходимости, но по мере выполнения процедуры (для обработки требуется около 2,5 миллионов записей) она сильно замедляется, например:

  • первые 20 000 записей: ~12 минут
  • секунда 20 000 записей: ~24 минуты
  • третьи 20 000 записей: ~37 минут
  • четвертые 20 000 записей: ~52 минуты
  • и т.д...

Проверка V$TEMPORARY_LOBS во время работы показывает, что значение CACHE_LOBS увеличивается с каждой обрабатываемой строкой. Я предполагаю, что это означает, что память, связанная с LOBS (в данном случае CLOBS), не освобождается после того, как она была использована...?

Пошаговое выполнение кода с помощью отладчика PL/SQL показывает, что значение CACHE_LOBS увеличивается на 2 при каждом вызове функции REPLACE. Вызовы функций соответствуют следующим строкам:

clobRTFText         CLOB;
...
dbms_lob.createtemporary(clobRTFText, TRUE, dbms_lob.call);
...
clobRTFText := REPLACE(clobRTFText, '<CR>', '\par ');  <== Causes CACHE_LOBS to increase by 2
...
dbms_lob.freetemporary(clobRTFText); <== Doesn't seem to cause CACHE_LOBS to decrease 

Как будто третья строка кода выше создает дополнительные переменные CLOB на лету. Это потому, что происходит какое-то неявное преобразование типа из-за того, что функция REPLACE ожидает параметр VARCHAR2? Я пытался использовать dbms_lob.copy вместо "clobRTFText := REPLACE...etc", но на самом деле это было хуже (т.е. CACHE_LOBS увеличивался еще быстрее). Какой бы ни была причина, вызов dbms_lob.freetemporary, по-видимому, не влияет на значение CACHE_LOBS.

Я просмотрел раздел PL/SQL Semantics for LOB в Oracle документация - в ней упоминается способ использования переменных CLOB и VARCHAR2 во встроенных функциях, но я не могу найти ничего об этом, что может привести к дополнительному использованию памяти.

Есть ли у кого-нибудь идеи, почему это происходит или как я могу это сделать (т.е. использовать REPLACE с CLOB), не освобождая память (при условии, что это действительно происходит)?

Спасибо


person user2724502    schedule 28.08.2013    source источник
comment
Вы пытались не кэшировать лобы? как в dbms_lob.createtemporary(clobRTFText, FALSE, dbms_lob.call);   -  person Vincent Malgrat    schedule 28.08.2013
comment
Я не вижу того же самого с парой вариантов зацикливания того, что вы показали; счетчик lob_cache действительно увеличивается на 2 для replace, но только в первый раз для прицела. Я никогда не вижу, чтобы значение превышало 3 или 4. Предположительно, я делаю что-то другое, поэтому не могли бы вы рассказать, как это вызывается и что еще оно делает? В идеале полная урезанная версия, которая показывает поведение.   -  person Alex Poole    schedule 28.08.2013
comment
У вас есть несколько локаторов? Из документации DBMS_LOB: Копия временного большого объекта создается, если пользователь изменяет временный большой объект, когда на него также указывает другой локатор. Локатор, для которого было выполнено изменение, теперь указывает на новую копию временного большого объекта.   -  person user272735    schedule 28.08.2013


Ответы (1)


Зачем делать это процедурно? Кажется, что декларативный подход удовлетворяет требованиям.

UPDATE clob_table SET clob_column = REPLACE(clob_column, '<CR>', '\par ');

Вы можете указать любое предложение WHERE, которое вам подходит.

person Michael O'Neill    schedule 04.09.2013