2009-10-06 34 views
8

Sono in esecuzione query su Oracle 10g con JDBC (utilizzando i driver più recenti e UCP come DataSource) per recuperare i CLOB (con 20 caratteri medi). Tuttavia, le prestazioni sembrano essere piuttosto negative: il recupero in batch di 100 LOB richiede in media 4 secondi. L'operazione non è né I/O, né CPU né rete legata a giudicare dalle mie osservazioni.Prestazioni Oracle CLOB

La mia configurazione di prova si presenta così:

PoolDataSource dataSource = PoolDataSourceFactory.getPoolDataSource(); 
dataSource.setConnectionFactoryClassName("..."); 
dataSource.setConnectionPoolName("..."); 
dataSource.setURL("..."); 
dataSource.setUser("..."); 
dataSource.setPassword("..."); 

dataSource.setConnectionProperty("defaultRowPrefetch", "1000"); 
dataSource.setConnectionProperty("defaultLobPrefetchSize", "500000"); 

final LobHandler handler = new OracleLobHandler(); 
JdbcTemplate j = new JdbcTemplate(dataSource); 

j.query("SELECT bigClob FROM ...", 

     new RowCallbackHandler() { 

      public void processRow(final ResultSet rs) throws SQLException { 

       String result = handler.getClobAsString(rs, "bigClob"); 

      } 

     }); 

} 

ho sperimentato con le dimensioni prelevare ma senza alcun risultato. Sto facendo qualcosa di sbagliato? C'è un modo per accelerare il recupero di CLOB quando si utilizza JDBC?

+0

Come è stato determinato che non è collegato alla rete? Stai parlando di impostare una nuova connessione JDBC (costosa), 2 MB di dati da leggere dal disco, inviarlo tramite la rete e il sovraccarico della query (che non è specificato). Non so se 4s è così male a seconda del layout di rete e della configurazione del database. – Gandalf

+0

Chiarimento: Misuro in * unità * di 100 quindi la penalità iniziale di collegamento non conta. Il throughput di rete totale rimane inferiore a 2 Mbit/s, quindi suppongo che non sia legato alla rete. – yawn

+0

Quanto dura la query effettiva? – Gandalf

risposta

2

Grazie per tutti i suggerimenti utili. Nonostante sia stata segnalata come risposta al problema, la mia risposta è che non sembra esserci una buona soluzione. Ho provato ad usare istruzioni parallele, diverse caratteristiche di memoria, temp pre-impostato. tavoli e altre cose. L'operazione sembra non essere legata a nessuna caratteristica visibile attraverso tracce o piani di spiegazione. Anche il parallelismo delle query sembra essere approssimativo quando sono coinvolti i CLOB.

Indubbiamente ci sarebbero migliori opzioni da gestire con CLOB di grandi dimensioni (soprattutto compressione) in un ambiente 11g ma atm. Sono bloccato con 10g.

Ho optato ora per un ulteriore roundtrip al database in cui eseguirò il preprocesso dei CLOB in un RAW binario ottimizzato per le dimensioni. Nelle distribuzioni precedenti questa è sempre stata un'opzione molto veloce e probabilmente vale la pena di mantenere una cache calcolata offline. La cache verrà invalida e aggiornata utilizzando un processo persistente e AQ finché qualcuno non avrà un'idea migliore.

+0

Sembra una buona soluzione, come se si recuperi 100 righe, si pagherà anche il viaggio di andata e ritorno ma si risparmiano 100 roundtrip, in totale si risparmiano 100-1 = 99 viaggi di andata e ritorno. Ma come lo hai implementato? – user451795

+0

Recuperando solo CLOB + una chiave per identificarli successivamente e scriverli in un archivio di valori-chiave locale. Ho usato [Oracle Berkeley DB] (http://www.oracle.com/technetwork/database/berkeleydb/overview/index.html) ma potresti facilmente usare SQLite o qualsiasi altra cosa suppongo. – yawn

6

La dimensione totale del set di risultati è nelle decine di migliaia - misurata nell'arco di tutto il recupero dei costi iniziali

C'è un Per ordine nella query? Le file 10K sono piuttosto numerose se devono essere ordinate.

Inoltre, il recupero del PK non è un test equo rispetto al recupero dell'intero CLOB. Oracle memorizza le righe della tabella con probabilmente molti in un blocco, ma ciascuno dei CLOB (se sono> 4K) verrà archiviato fuori linea, ciascuno in una serie di blocchi. Scansionare la lista dei PK sarà quindi veloce. Inoltre, c'è probabilmente un indice sul PK, quindi Oracle può solo eseguire rapidamente la scansione dei blocchi indice e nemmeno accedere alla tabella.

4 secondi sembra un po 'alto, ma è di 2 MB che deve essere possibile leggere dal disco e trasportato in rete al programma Java. La rete potrebbe essere un problema. Se si esegue una traccia SQL della sessione, verrà indirizzato esattamente dove viene trascorso il tempo (lettura del disco o rete).

5

La mia esperienza passata nell'utilizzo di dati di tipo LOB oracle per archiviare dati di grandi dimensioni non è stata buona. Va bene quando è sotto 4k poiché lo memorizza localmente come varchar2. Una volta superato il 4k, si inizia a vedere il degrado delle prestazioni. Forse, le cose potrebbero essere migliorate da quando l'ho provato l'ultima volta un paio di anni fa, ma qui ci sono le cose che ho trovato in passato:

Poiché i client devono ottenere LOB tramite il server Oracle, è possibile considerare quanto segue situazione interessante.

  • dati pallonetto competerà limitata della cache SGA con altro tipo di dati se Oracle decide di memorizzare nella cache esso. Poiché i dati CLOB sono generale grande, quindi potrebbe spingere altri dati
  • dati LOB ottenere poveri disco leggere se oracolo decidere di non memorizzare nella cache, e streaming i dati al client.
  • la frammentazione è probabilmente qualcosa di che non hai ancora incontrato. Vedrai se le tue applicazioni eliminano i lob e oracle cerca di riutilizzare il lob. Non so se il supporto oracle deframmenta online il disco per il lob (hanno per gli indici, ma ci vuole molto tempo quando lo abbiamo provato in precedenza).

Hai menzionato 4s per 100 lob di avg 20k, quindi è 40ms per lob. Ricorda che ogni pallonetto deve essere recuperato tramite Lob locater separato (non è nel set di risultati di default). Questo è un giro di andata e ritorno per ogni pallonetto, presumo (non sono sicuro al 100% su questo dato che era un po 'di tempo fa) In questo caso, suppongo che saranno almeno 5ms di tempo extra per andata e ritorno in ordine seriale , destra? In tal caso, le tue prestazioni sono già limitate in primo luogo dai recuperi sequenziali dei lob.Dovresti essere in grado di verificarlo tracciando il tempo trascorso nell'esecuzione di SQL vs il recupero di contenuti lob. Oppure puoi verificarlo escludendo la colonna del lob come suggerito dalla risposta precedente nel post, che dovrebbe dirti se è legata al lobo.

Buona fortuna

3

Avevo un problema simile e ho trovato il JDBC Lobs effettuare una chiamata di rete quando si accede ai lob.

A partire dal driver JDBC Oracle 11.2g è possibile utilizzare un prefetch. Questo accesso velocizzato di 10 volte ...

statement1.setFetchSize(1000); 
if (statement1 instanceof OracleStatement) { 
    ((OracleStatement) statement1).setLobPrefetchSize(250000); 
} 
Problemi correlati