2013-08-28 45 views
5

Mam wymóg użycia wbudowanej funkcji REPLACE dla zmiennej CLOB w ramach większego procesu PL/SQL. Używam Oracle 11g R2, a funkcja działa poprawnie, ponieważ zastępuje ją zgodnie z wymaganiami, ale z uruchomioną procedurą (do przetworzenia jest około 2,5 miliona rekordów), spowalnia to źle - jak w:Dlaczego użycie funkcji REPLACE dla obiektu CLOB powoduje wzrost wartości CACHE_LOBS ...?

  • pierwsze 20.000 rekordy: ~ 12 minut
  • drugi 20.000 wyniki: ~ 24 minut
  • trzecie 20.000 wyniki: ~ 37 minut
  • czwarty 20.000 wyniki: ~ 52 minut
  • etc ...

Sprawdzanie V $ TEMPORARY_LOBS podczas operacji pokazuje, że wartość dla CACHE_LOBS wzrasta z każdym przetwarzanym wierszem - moje założenie jest takie, że implikuje to, że pamięć skojarzona z LOBS (w tym przypadku CLOBS) nie zostanie zwolniona, gdy zostanie użyta ...?

Krok po kroku za pomocą debuggera PL/SQL pokazuje, że wartość dla CACHE_LOBS wzrasta o 2 dla każdego wywołania funkcji REPLACE. Wywołania funkcji są wzdłuż linii:

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 

To jakby trzecia linia kodu powyżej jest tworzenie dalszych zmiennych CLOB w locie. Czy to dlatego, że istnieje jakaś niejawna konwersja typów spowodowana funkcją REPLACE, która oczekuje parametru VARCHAR2? Próbowałem używać dbms_lob.copy zamiast "clobRTFText: = REPLACE ... etc", ale w rzeczywistości było gorzej (tj. CACHE_LOBS jeszcze szybciej się zwiększyło). Niezależnie od powodu, wywołanie dbms_lob.freetemporary nie wydaje się mieć żadnego znaczenia dla wartości CACHE_LOBS.

Przeszedłem przez sekcję PL/SQL Semantics for LOBs dokumentacji Oracle - wspomina o sposobie wykorzystania zmiennych CLOB i VARCHAR2 we wbudowanych funkcjach, ale nie mogę znaleźć niczego, co mogłoby spowodować dodatkowe zużycie pamięci.

Czy ktoś ma jakieś pomysły, dlaczego tak się dzieje lub jak mógłbym to zrobić (tj. Użyć REPLACE z CLOB) bez tego, że nie zwalnia pamięci (zakładając, że tak się dzieje)?

Dzięki

+1

Czy próbowałeś nie przechowywać w pamięci podręcznej płyt? jak w 'dbms_lob.createtemporary (clobRTFText, FALSE, dbms_lob.call);' –

+2

Nie widzę tego samego z kilkoma odmianami pętli nad tym, co pokazałeś; liczba 'lob_cache' zwiększa się o 2 dla' replace', ale tylko po raz pierwszy dla zakresu. Nigdy nie widzę wartości przekraczającej 3 lub 4. Przypuszczam, że robię coś innego, więc czy możesz rozwinąć to, jak to się nazywa i co jeszcze robi? Idealnie kompletna wersja, która pokazuje zachowanie. –

+1

Czy masz wiele lokalizatorów? Z dokumentacji [DBMS_LOB] (http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/d_lob.htm#i1015757): _ Kopia tymczasowego LOB jest tworzona, jeśli użytkownik modyfikuje tymczasowy LOB podczas gdy inny lokalizator również wskazuje na to. Lokalizator, na którym dokonano modyfikacji, wskazuje teraz na nową kopię tymczasowego LOB. – user272735

Odpowiedz

1

Dlaczego to proceduralnie? Wydaje się, że podejście deklaratywne spełnia wymagania.

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

Można dostarczyć cokolwiek WHERE klauzulę, który Ci odpowiada.