Untitled Document
   
 
Indicazioni inerenti le prestazioni per il data tier con JDBC
di Jhon Goodson, traduzione di Antonella Bellettini

Introduzione
Lo sviluppo di applicazioni JDBC mirate all'ottimizzazione delle prestazioni non è semplice. I driver JDBC non lanciano alcuna eccezione per segnalare quando il codice in esecuzione è tropo lento.

La seguente serie di indicazioni relative alle prestazioni presenta alcune linee guida di valenza generale per il miglioramento dell'efficienza di un'applicazioni JDBC, la cui stesura è stata realizzata a seguito dell'esame di numerose implementazioni di applicazioni JDBC correntemente rilasciate. Queste linee guida includono:

  • Utilizzo appropriato dei metodi per database che sfruttano i metadata
  • Recupero dei soli dati richiesti
  • Selezione di funzioni che ottimizzano le prestazioni
  • Gestione delle connessioni e degli aggiornamenti

L'attenersi a queste regole generali aiuta la risoluzione di alcuni problemi comuni di prestazione dei sistemi JDBC.

 

Utilizzo dei metodi per database che sfruttano i metadata
Poiché i metodi per database che fanno uso dei metadata e che generano oggetti del ResultSet sono lenti rispetto ad altri metodi JDBC, il loro utilizzo frequente può deteriorare le prestazioni del sistema.

Minimizzazione dell'utilizzo dei metodi per database che sfruttano i metadata
Confrontati con altri metodi JDBC, i metodi per database che fanno uso dei metadata e che generano oggetti del ResultSet sono relativamente lenti. Per evitare la necessità di esecuzioni multiple, le applicazioni dovrebbero conservare nelle memoria cache informazioni restituite dai set dei risultati che generano i metodi per database basati sui metadata.

Anche se quasi nessuna applicazione JDBC può essere scritta senza utilizzare metodi facenti uso dei metadata, le prestazioni del sistema possono essere migliorate minimizzando il ricorso a tali metodi. Per restituire tutte le informazioni delle colonne di risultati richieste dalle specifiche JDBC, un driver JSP può trovarsi a dovere eseguire query complesse o multiple per ritornare il set dei risultati necessario per una singola chiamata a un metodo per database che sfrutti i metadata. Questi elementi particolari del linguaggio SQL sono costosi dal punto di vista delle prestazioni.

Le applicazioni dovrebbero conservare nelle memoria cache informazioni provenienti dai metodi facenti uso dei metadata. Per esempio, si chiami una volta getTypeInfo nell'applicazione e si mantengano memorizzati a parte gli elementi dai quali dipende la propria applicazione. E' improbabile che un'applicazione faccia uso di tutti gli elementi del set dei risultati generato da un metodo per database basato su metadata, perciò non dovrebbe essere difficile conservare le informazioni nella memoria di cache.

Evitare pattern di ricerca
L'utilizzo di argomenti nulli o pattern di ricerca in metodi per database facenti uso di metadata, determina la generazione di query che consumano tempo. In aggiunta, il traffico di rete cresce potenzialmente a causa dei risultati indesiderati. Si deve quindi cercare sempre di fornire il maggior numero possibile di argomenti non nulli ai set dei risultati che generano metodi per database basati su metadata.

Essendo i metodi di tale tipo lenti, le applicazioni dovrebbero invocarli nel modo più efficiente possibile. Molte applicazioni passano solo argomenti non nulli nel numero minimo necessario per il successo della chiamata alla funzione.

Per esempio:

ResultSet WSrs = WSc.getTables (null, null, "WSTable", null);

dovrebbe essere:

ResultSet WSrs = WSc.getTables ("cat1", "johng", "WSTable","TABLE");

Nella prima chiamata a getTable(), l'applicazione probabilmente vuole sapere se la tabella WSTable esiste. Un driver JDBC, naturalmente, considera la chiamata in modo "letterale" e interpreta la richiesta in diversamente. Un driver JDBC interpreta la richiesta come segue: restituisci tutte le tabelle, le view, le tabelle di sistema, i sinonimi, le tabelle temporanee o gli alias che esistono in ogni schema di database, all'interno di ogni catalogo di database, che siano denominati 'WSTable'.

La seconda chiamata a getTable() rispecchia più accuratamente ciò che l'applicazione vuole fare. Un driver JDBC interpreta tale richiesta nel modo seguente: restituisce tutte le tabelle esistenti nello schema 'johng' del presente catalogo il cui nome sia 'WSTable".

E' evidente che un driver JDBC può elaborare la seconda richiesta in modo assai più efficiente di quanto non possa fare con la prima.

Spesso, si dispone di pochi DATI relativamente all'oggetto su cui si stanno chiedendo informazioni. Qualsiasi informazione che l'applicazione può inviare al driver, mentre chiama metodi facenti uso di metadata, può indurre un miglioramento sia delle prestazioni che dell'affidabilità.

Utilizzo di dummy query per determinare le caratteristiche delle tabelle
Si eviti l'uso di getColumns() per determinare le caratteristiche relative ad una tabella. Si utilizzi invece una dummy query con getmetadata().

Si consideri un'applicazione che permette all'utilizzatore di scegliere le colonne che saranno selezionate. Sarebbe conveniente per l'applicazione utilizzare getColumns() per fornire all'utente informazioni sulle colonne o dovrebbe, piuttosto, preparare una dummy query e chiamare getmetadata()?

Caso 1: Metodo getColumns

ResultSet WSrc = WSc.getColumns (... "UnknownTable" ...);
// This call to getColumns() will generate a query to
// the system catalogs... possibly a join
// which must be prepared, executed, and produce
// a set dei risultati
. . .
WSrc.next();
string Cname = getString(4);
. . .
// user must retrieve N rows from the server
// N = # result columns of UnknownTable
// result column information has now been obtained

Caso 2: Metodo getmetadata

// prepare dummy query
PreparedStatement WSps = WSc.prepareStatement
("SELECT * from UnknownTable WHERE 1 = 0");
// query is never executed on the server - only prepared
ResultSetmetadata WSsmd=WSps.getmetadata();
int numcols = WSrsmd.getColumnCount();
...
int ctype = WSrsmd.getColumnType(n)
...
// result column information has now been obtained

In entrambi i casi, viene inviata una query al server. Ma nel Caso 1 deve essere preparata ed eseguita la query, deve essere formulata la descrizione delle informazioni risultanti, e deve essere mandato al client un set dei risultati di righe. Nel Caso 2 invece è unicamente necessario che venga preparata una semplice query e venga formulata la descrizione delle informazioni risultanti. E' palese che il Caso 2 è un modello che presenta prestazioni migliori.

Per complicare un poco questa discussione, si consideri un server DBMS che di per sé non supporti la generazione di un comando SQL. Le prestazioni nel Caso 1 non mutano, mentre nel Caso 2 migliorano leggermente, poiché la dummy query deve essere valutata invece che solo preparata. Dato che l'istruzione 'Where close' dà sempre il valore FALSE, la query non fornisce come risultato alcuna riga e dovrebbe effettuare l'esecuzione senza accedere a dati della tabella. Per questa ragione il secondo metodo supera in prestazioni il primo.

Riassumendo, vanno utilizzati sempre metadata del set dei risultati per ricercare informazioni relative alle colonne della tabella quali i nomi di colonna, i tipi di dati di colonna, la precisione e la scala di colonna. E' opportuno l'uso di getColumns() quando le informazioni richieste non possono essere ottenute da metadata del set dei risultati (cioè per i valori di default delle colonne della tabella).

Cercate, nel numero del prossimo mese, ulteriori suggerimenti sulle prestazioni, in particolare sul 'Ricupero dei soli dati richiesti'.

L'articolo è stato originariamente pubblicato su TheServerSide.com