2013-08-28 16 views
5

Ho un requisito per utilizzare la funzione REPLACE incorporata su una variabile CLOB come parte di un processo PL/SQL più grande. Sto usando Oracle 11g R2 e la funzione funziona OK, in quanto sostituisce come richiesto, ma mentre la procedura viene eseguita (ci sono circa 2,5 milioni di record da elaborare), rallenta male - come in:Perché l'uso della funzione REPLACE su CLOB causa un aumento di CACHE_LOBS ...?

  • primi 20.000 record: ~ 12 minuti
  • secondo 20.000 record: ~ 24 minuti
  • terzo 20.000 record: ~ 37 minuti
  • quarto 20.000 record: ~ 52 minuti
  • ecc ...

Il controllo di V $ TEMPORARY_LOBS durante l'operazione mostra che il valore di CACHE_LOBS aumenta con ogni riga elaborata, suppongo che ciò implichi che la memoria associata a LOBS (in questo caso CLOBS) non venga rilasciata una volta utilizzata ...?

Passare attraverso il codice utilizzando il debugger PL/SQL rivela che il valore di CACHE_LOBS aumenta di 2 per ogni chiamata alla funzione REPLACE. Le chiamate di funzione sono lungo le linee di:

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 

È come se la terza riga di codice precedente crea ulteriori variabili CLOB al volo. È perché c'è una specie di conversione di tipo implicita che si verifica a causa della funzione REPLACE che prevede un parametro VARCHAR2? Ho provato a usare dbms_lob.copy invece di "clobRTFText: = REPLACE ... etc", ma in realtà è stato peggio (cioè CACHE_LOBS è aumentato ancora più velocemente). Qualunque sia la ragione, la chiamata a dbms_lob.freetemporary non sembra fare alcuna differenza per il valore di CACHE_LOBS.

Ho esaminato la sezione PL/SQL Semantics for LOBs della documentazione di Oracle, menzionando il modo in cui le variabili CLOB e VARCHAR2 possono essere utilizzate nelle funzioni incorporate, ma non riesco a trovare nulla che possa causare potenzialmente un utilizzo extra della memoria.

Qualcuno ha qualche idea del perché questo sta accadendo o di come potrei farlo (cioè utilizzare REPLACE con un CLOB) senza che non riesca a rilasciare memoria (supponendo che sia effettivamente ciò che sta accadendo)?

Grazie

+1

Hai provato a non memorizzare nella cache i lob? come in 'dbms_lob.createtemporary (clobRTFText, FALSE, dbms_lob.call);' –

+2

Non vedo la stessa cosa con un paio di varianti di loop su ciò che hai mostrato; il conteggio 'lob_cache' aumenta di 2 per' replace', ma solo la prima volta per l'ambito. Non vedo mai un valore superiore a 3 o 4. Presumibilmente sto facendo qualcosa di diverso, quindi puoi approfondire come viene chiamato e che altro sta facendo? Idealmente una versione completa del cut-down che mostra il comportamento. –

+1

Hai più localizzatori? Dalla documentazione di [DBMS_LOB] (http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/d_lob.htm#i1015757): _Una copia di un LOB temporaneo viene creata se l'utente modifica il LOB temporaneo mentre un altro localizzatore lo sta anche indicando. Il localizzatore su cui è stata eseguita una modifica ora punta a una nuova copia della LOB temporanea. – user272735

risposta

1

Perché farlo in modo procedurale? Sembra che un approccio dichiarativo soddisfi i requisiti.

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

puoi fornire qualunque WHERE clausola che fa per voi.