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
Hai provato a non memorizzare nella cache i lob? come in 'dbms_lob.createtemporary (clobRTFText, FALSE, dbms_lob.call);' –
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. –
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