Встала задачка собрать много строчек таблицы в один BLOB.
Краткий алгоритм как это сделать: делаем temporary lob - изменяем его, вставляя строки - вставляем - очищаем - возвращаемся к шагу 1.
В нижележащих тестах разница, на сколько отличается по времени работа с temporary lob, созданного с параметром cache = true и cache = false
Результаты: cache = true в 20 раз быстрее
Код и результата теста
SET SERVEROUTPUT ON
PROMPT CACHE=TRUE
DECLARE
bl BLOB;
l_raw RAW(32767);
l_temp_cnt NUMBER;
l_start_time NUMBER := dbms_utility.get_time;
FUNCTION get_temp_blocks_cnt RETURN NUMBER IS
l_cnt NUMBER;
BEGIN
SELECT SUM(u.blocks)
INTO l_cnt
FROM v$tempseg_usage u, v$session s
WHERE u.session_addr = s.saddr AND AUDSID = USERENV('SESSIONID');
RETURN NVL(l_cnt, 0);
END;
BEGIN
l_temp_cnt := get_temp_blocks_cnt;
DBMS_LOB.createtemporary(bl, TRUE);
FOR i IN 1 .. 100000 LOOP
l_raw := utl_raw.cast_to_raw(RPAD(i, 1000, ' '));
dbms_lob.writeappend(bl, utl_raw.length(l_raw), l_raw);
IF MOD(i, 10) = 0 THEN
dbms_lob.freetemporary(lob_loc => bl);
DBMS_LOB.createtemporary(bl, TRUE);
END IF;
END LOOP;
dbms_output.put_line('Temp used=' || (get_temp_blocks_cnt - l_temp_cnt));
dbms_output.put_line('Time used ' || (dbms_utility.get_time - l_start_time) / 100);
END;
/
PROMPT CACHE=FALSE
DECLARE
bl BLOB;
l_raw RAW(32767);
l_temp_cnt NUMBER;
l_start_time NUMBER := dbms_utility.get_time;
FUNCTION get_temp_blocks_cnt RETURN NUMBER IS
l_cnt NUMBER;
BEGIN
SELECT SUM(u.blocks)
INTO l_cnt
FROM v$tempseg_usage u, v$session s
WHERE u.session_addr = s.saddr AND AUDSID = USERENV('SESSIONID');
RETURN NVL(l_cnt, 0);
END;
BEGIN
l_temp_cnt := get_temp_blocks_cnt;
DBMS_LOB.createtemporary(bl, FALSE);
FOR i IN 1 .. 100000 LOOP
l_raw := utl_raw.cast_to_raw(RPAD(i, 1000, ' '));
dbms_lob.writeappend(bl, utl_raw.length(l_raw), l_raw);
IF MOD(i, 10) = 0 THEN
dbms_lob.freetemporary(lob_loc => bl);
DBMS_LOB.createtemporary(bl, FALSE);
END IF;
END LOOP;
dbms_output.put_line('Temp used=' || (get_temp_blocks_cnt - l_temp_cnt));
dbms_output.put_line('Time used ' || (dbms_utility.get_time - l_start_time) / 100);
END;
/
CACHE=TRUE
Temp used=0
Time used 2.08
PL/SQL procedure successfully completed
CACHE=FALSE
Temp used=0
Time used 42.29
PL/SQL procedure successfully completed
Примечательно, что единственный способ, который сработал для очистки BLOB это
dbms_lob.freetemporary(lob_loc => bl);
DBMS_LOB.createtemporary(bl);
Ни присвоение NULL, ни empty_blob, который работает только для insert и select, как оказалось из найденной документации от версии 8.1
An exception is raised if you use these functions anywhere but in the VALUES clause of a SQL INSERT statement or as the source of the SET clause in a SQL UPDATE statement.
А для свежих версий
You cannot use the locator returned from this function as a parameter
to the DBMS_LOB package or the OCI.
Для дальнейших исследований можно заняться замерами потребляемой памяти.
Комментариев нет:
Отправить комментарий