In questo documento vengono esaminati i principali aspetti tecnici di Oracle di impatto sulle prestazioni sia dal punto di vista della programmazione che dal punto di vista dell'amministrazione.
Questo documento riporta alcuni aspetti tecnici specifici di Oracle di interesse ai programmatori applicativi. E' pertanto di interesse a chi debba utilizzare funzioni specifiche di tale RDBMS come programmatore. Alcuni elementi trattati possono comunque essere di interesse per l'amministratore, o l'utente finale.
Per ogni punto analizzato vengono presentate alcune regole ed elementi di standard cui e' opportuno attenersi nello sviluppo di progetti.
Gli argomenti sono stati trattati con un certo dettaglio con lo scopo di ottenere un miglioramento delle prestazioni.
L'obiettivo di questo documento non e' certamente la completezza, per una trattazione piu' completa ed esaustiva e' necessario fare riferimento alla specifica documentazione e manualistica.
Si e' piuttosto cercato di fornire un'ampia panoramica di elementi di utilita' e di interesse a chi deve accedere all'RDBMS Oracle con un'interfaccia programmatica o a chi dovesse migliorare le prestazioni di un sistema esistente.
In questo breve capitolo sono raccolti alcuni punti che impattano sulle scelte e sulle attivita' di interesse per i gruppi applicativi. Per ogni argomento vengono indicate le funzionalita' dell'RDBMS ed alcune scelte di riferimento da adottare nello sviluppo.
Locking e transazioni
Gli attuali RDBMS forniscono un completo supporto per la gestione delle transazioni e della concorrenza. Per consentire l'utilizzo in contemporanea degli stessi dati da parte di piu' utenti o applicazioni e' necessario fornire un servizio di blocco dei dati in modifica (lock). Una transazione e' un insieme di operazioni che debbono essere eseguite tutte contemporaneamente oppure non essere eseguite affatto.
Oracle offre possibilita' per la gestione dei lock e delle transazioni. Tra le principali caratteristiche:
E' importante gestire correttamente la logica transazionale nei programmi applicativi. In particolare:
Dall'analisi funzionale debbono essere ben definite le transazioni necessarie per l'implementazione. La gestione delle transazioni deve essere completa ed accurata da parte dell'applicativo: le unita' logiche debbono essere sempre rispettate. Le tipologie di problemi che altrimenti insorgono, il controllo di tali anomalie e le soluzioni a posteriori sono altrimenti assai complesse.
Integrita' dei dati
L'integrita' dei dati del database e' garantita dai Constraints, vincoli che regolano la manipolazione dei dati e che sostituiscono il controllo da parte dell'applicazione, piu' costoso e meno sicuro.
I Constraints sono:
NOT NULL colonna da valorizzare
UNIQUE colonna senza valori duplicati
PRIMARY KEY identifica la riga nella tavola
FOREIGN KEY referenzia la primary key di un'altra tavola
CHECK controlla i valori inseriti nelle tabelle utilizzando condizioni SQL
E' opportuno utilizzare i constraint: NOT NULL, PRIMARY KEY ed UNIQUE. L'utilizzo di foreign key deve essere valutato con attenzione per i vantaggi sulla qualita' dei dati che ne derivano e la maggior difficolta' di gestione della base dati. E' in genere opportuno (per motivi di efficienza) creare indici secondari per le foreign key.
Indici
L'accesso alle tabelle di un database relazionale per effettuare ricerche o join e' notevolmente piu' efficiente se si utilizzano indici.
La creazione degli indici e' quindi di notevole importanza per ottenere un sistema informativo ben performante. L'indicazione sugli indici da creare su un database relazionale deve essere fornita da chi sviluppa le applicazioni. Il programmatore infatti conosce i diversi accessi effettuati verso i dati.
Accesso al database in rete
Oracle consente un accesso trasparente ai database disponibili in rete. Una connessione ad un database esterno e' del tutto identica ad una sessione locale. La differenza e' semplicemente nella stringa che viene utilizzata all'atto della connessione. Nel caso di connessione remota deve infatti essere indicata la lettera che identifica il protocollo di comunicazione utilizzato e quindi una serie di parametri specifici del protocollo. Per i normali protocolli di transport utilizzabili, tali parametri sono il nome della macchina su cui il database risiede ed il nome del database su tale macchina (i parametri sono riportati nella stringa di connessione con SQL*Net v1, nel caso di utilizzo di SQL*Net v2 tali elementi vengono invece descritti su file).
Oracle inoltre consente la definizione di collegamenti tra tabelle in rete. In questo caso ad una tabella (che dal punto di vista SQL e' trattata come una tabella locale) corrisponde in realta' un accesso in remoto. Tale accesso nella versione 6 era esclusivamente in lettura, mentre dalla versione 7 puo' essere anche in scrittura consentendo la scrittura di transazioni distribuite. L'utilizzo dell'accesso in scrittura su tabelle remote e' gestito mediante il protocollo di two phase commit. L'accesso a dati remoti puo' essere reso trasparente agli applicativi mediante viste e sinonimi.
Tra le nuove funzionalita' della versione 7 vi e' anche quella relativa ai database snapshot che viene descritta nel seguito ed in altri documenti.
L'accesso a database remoti non presenta particolari problemi mentre la costruzione di transazioni distribuite e' da valutare con attenzione. L'uso di transazioni distribuite e' utilizzabile nel caso di reti locali veloci e non cariche per transazioni brevi e limitate nel numero.
Controllo dell'integrita' applicativa
E' possibile la definizione di alcune "regole" applicative sui dati che possono venire controllate da opportuni programmi di verifica della qualita' dei dati. In questo modo e' possibile controllare esternamente ai programmi in linea la validita' dei controlli e delle operazioni effettuate sui dati.
E' opportuna la definizione di tali regole sui dati e la creazione di opportuni programmi di controllo.
Dimensionamento tabelle
Oracle permette una definizione molto precisa ed orientata al raggiungimento delle migliori prestazioni per le varie strutture fisiche della base dati. Il tipo di strategia utilizzata da Oracle porta alla preallocazione delle risorse necessarie.
Per una corretta definizione delle strutture fisiche della base dati e' percio' importante conoscere compiutamente la dimensione di ogni oggetto presente nella base dati e la tipologia di utilizzo.
Dall'analisi dei requisiti utente debbono emergere gli elementi necessari al corretto dimensionamento. Il dimensionamento di ogni tabella (e di ogni altro oggetto: indici, cluster, ..) deve essere effettuato nella fase di disegno fisico della base dati (che fa parte dello sviluppo) anche se alcuni elementi debbono essere tenuti in considerazione nelle precedenti fasi di analisi. E' opportuno un tuning finale delle dimensioni a database avviato.
La clausola SQL per il dimensionamento degli oggetti e' quella di STORAGE (INITIAL x NEXT y ..).
Gestione degli errori
L'RDBMS Oracle fornisce una lista di errori molto ampia e di notevole importanza per il controllo del corretto funzionamento degli applicativi e per la gestione di eventuali problemi. E' di particolare importanza controllare le varie possibilita' di errore degli statement SQL e gestire di conseguenza la situazione.
La versione 7.0 di Oracle introduce una nuova serie di errori relativi alla violazione dei vincoli di integrita' dei dati.
E' opportuno che le modalita' applicative di gestione degli errori siano complete e comuni a tutti gli accessi alle basi dati.
Definizione della frequenza e modalita' di accesso ai dati
Oracle permette una definizione molto precisa ed orientata al raggiungimento delle migliori prestazioni di diversi parametri di configurazione e tuning. Per una corretta definizione di tali parametri e' necessario conoscere compiutamente le modalita' di accesso ai dati degli applicativi.
Dall'analisi funzionale debbono emergere indicazioni sui tipi e le frequenze di accesso ai dati in modo da definire opportunamente gli indici secondari ed gli eventuali parametri di Oracle.
Vi sono alcuni elementi caratteristici dell'RDBMS Oracle che, in genere, non sono presenti su altri RDBMS o che presentano aspetti di implementazione differenti. Conoscendo tali particolarita' e' possibile sfruttare appieno le possibilita' che l'RDBMS Oracle offre.
Vengono nel seguito riportati quegli aspetti che possono essere di maggior interesse o impatto per la scrittura di applicazioni.
Ottimizzatore e Hints
L'Ottimizzatore di ORACLE, di fronte a uno statement SQL e in base alle proprie informazioni sulle tavole e sugli indici, determina l'execution plan, il percorso che secondo lui e' il piu' efficiente per accedere ai dati ed eseguire lo statement. La versione 7.0 di Oracle e' molto ricca di possibilita' e consente la scelta tra un ottimizzatore cost-based (con ulteriori opzioni) ed un ottimizzatore rule-based (analogo a quello della versione 6.0).
L'ottimizzatore rule-based e' guidato dalla sintassi con cui l'utente scrive lo statement SQL.
L'ottimizzatore cost-based e' guidato nella definizione dell'execution-plan dalla dimensione delle tabelle e dalla selettivita' degli indici. Con l'ottimizzatore cost-based il programmatore SQL, conoscendo a fondo le tavole e gli indici del database, puo' indirizzare l'Ottimizzatore tramite gli Hints, dei suggerimenti da fare seguire agli statements SQL. Affinche' l'ottimizzatore conosca i dimensionamenti delle varie tabelle e' necessario utilizzare il comando di ANALIZE.
La corretta individuazione del miglior percorso di accesso ai dati da parte dell'ottimizzatore e' fonadmentale come impatto prestazionale. Le differenze in tempi possono essere superiori al 1000%. Ulteriori elementi sull'argomento sono contenuti sul documento "Ottimizzazione dell'SQL".
Con l'ottimizzatore rule based e' di fondamentale importanza la corretta scrittura degli statement SQL.
Per l'ottimizzatore cost-based la definizione dei corretti suggerimenti da passare all'ottimizzatore non e' semplice. La miglior metodologia consiste nel effettuare un volume test degli applicativi e quindi concentrarsi sugli statement di maggior peso.
L'uso dell'ottimizzatore cost-based e' consigliabile soprattutto dalla versione 7.3
Dialetto SQL
Oracle offre diverse estensioni al linguaggio SQL. In particolare sono presenti parecchie funzioni per il trattamento dei dati; alcune delle quali non hanno analoghi su altri RDBMS (eg. decode). Utilizzando tali particolarita' e' spesso possibile semplificare i propri programmi. Deve essere tuttavia valutata la minor portabilita' che si ha utilizzando funzioni specifiche del prodotto.
Rilevanti sono infine le possibilita' del DDL che consente la completa gestione delle strutture dati.
Sequences
La sequence e' un oggetto ORACLE che genera numeri progressivi usato per creare chiavi primarie. E' necessario creare una sequence corrispondente alla tavola in questione e incrementarla del valore desiderato, di solito 1. L'opzione CACHE nella creazione della sequence permette di allocare in memoria un set di numeri della sequence in modo da accedervi piu' velocemente.
La sequence e' referenziata negli statements SQL con le pseudo-colonne NEXTVAL e CURRVAL. NEXTVAL genera un nuovo numero quando necessario. CURRVAL referenzia il numero corrente e puo' essere usato solo se NEXTVAL e' stato precedentemente usato nella sessione corrente.
Le sequenze possono essere utilizzate per la funzione di generazione della chiave univoca di una tabella. Tale utilizzo e' molto efficiente ed e' consigliato in tutti i casi in cui sia possibile.
SQL condiviso
Su RDBMS Oracle 7 se vengono utilizzati due statements SQL identici, l'area di memoria usata per processare la prima istanza dello statement e' condivisa, cioe' usata per processare le successive istanze dello statement, con conseguente risparmio di memoria. I vantaggi dal punto di vista prestazionale sono notevoli.
Nella versione 6 il parsing viene comunque effettuato.
E' quindi utile che statements e blocchi che eseguono operazioni simili usino il piu' possibile l'SQL condiviso. Per fare cio' gli statement SQL non debbono variare nella codifica ed utilizzare, per quanto possibile, hosts variables in tutti i casi in cui sia possibile.
Array processing
L'array processing permette all'applicazione di caricare piu' record risultanti da una selezione SQL facendo una sola chiamata a ORACLE, con conseguente miglioramento delle performance. Le prestazioni aumentano in particolare in ambienti client/server poiche' viene diminuito il traffico di rete (o meglio il round trip). Aumentando la dimensione dell'array si riduce il numero di chiamate a ORACLE, ma si aumenta anche la memoria richiesta.
Alcuni tools (SQL*Forms) usano automaticamente l'array processing. Con altri tools (SQL*Plus, Precompilatori) si puo' modificare la dimensione dell'array (es: set arraysize 100). In SQLRouter il parametro FETCHROW del file SQL.INI indica il numero massimo di righe ritrovate con una singola chiamata al server ORACLE (es: fetchrow=20).
E' suggerito l'utilizzo dell'array processing per le applicazioni (su macchine Unix) che abbiano esigenze di buone prestazioni (ovvero tutte!!). L'utilizzo dell'array processing da parte di SQLWindows e' automatico.
PL/SQL
Il PL/SQL permette di scrivere in un unico blocco diversi statement SQL e di passarli a ORACLE tutti assieme. Permette inoltre di usare funzioni procedurali che evitano chiamate successive a ORACLE.
L'utilizzo di stored procedures realizzate in PL/SQL puo' consentire buone prestazioni poiche' lo scambio di dati e' molto ridotto.
SQL dinamico
I tool di Oracle consentono la definizione di statement SQL a runtime. In tal modo viene cosi' garantita la massima flessibilita' nell'utilizzo del linguaggio SQL. Alcuni tool utilizzano un interfaccia di SQL dinamico in maniera diretta e trasparente (e.g. SQLWindows).
In alcuni casi l'SQL dinamico e' una necessita'. Per gli altri casi e' opportuno evitare l'utilizzo dell'SQL dinamico per diverse ragioni: efficienza nell'esecuzione, impossibilita' di controllo al momento della compilazione del codice, difficolta' nella codifica degli statement SQL, difficolta' nel controllo del codice SQL, difficolta' nel debug.
L'utilizzo dell'SQL in ambiente SQLWindows e' visto da Oracle in maniera sempre identica. La distinzione tra SQL dinamico e non in ambiente SQLWindows ha solo aspetti di tipo applicativo.
PRO*
Oracle offre, per diversi linguaggi di terza generazione, una interfaccia embedded SQL. Con tali precompilatori e' possibile annegare gli statement SQL nel normale programma scritto con il linguaggio prescelto.
Sono disponibili diversi flag di compilazione per l'ottimizzazione ed il controllo dei programmi.
Per utilizzo dei precompilatori e' opportuno costruire file di make che effettuino tutti i passi di compilazione necessari. Le opzioni di default dei precompilatori (nella versione 7) sono adatte alla maggioranza dei casi applicativi e quindi non richiedono particolari definizioni di parametri. Nella versione 6 e' invece opportuno controllare i parametri di rebind e di ricorsione.
Stored procedures e Packages
Le Stored Procedures sono procedure PL/SQL registrate nel database per un uso ripetuto da parte delle applicazioni. Il loro uso garantisce un comportamento costante tra le applicazioni e riduce i tempi di sviluppo e di test.
Le procedure correlate tra loro possono essere raggruppate in Packages.
Si tratta di una funzionalita' introdotta dalla versione Oracle 7.0.
Benche' l'utilizzo di stored procedures possa essere molto efficiente in applicazioni client-server deve esserne valutato l'utilizzo poiche' di difficile portabilita' su database non Oracle.
Database Triggers
I Database Triggers sono procedure registrate nel database e automaticamente eseguite quando il database viene modificato.
I Database Triggers sono usati per garantire che determinate operazioni siano sempre eseguite, indipendentemente dall'utente o dall'applicazione che modifica il database.
Queste procedure sono legate agli statements INSERT, DELETE e UPDATE dalle opzioni BEFORE o AFTER.
Si tratta di una funzionalita' di Oracle 7.0.
L'utilizzo corretto di database trigger puo' evitare la scrittura di codice nelle applicazioni garantendo una costante applicazione di procedure predefinite. Nel caso in cui il risparmio sia rilevante, per applicazioni che accedano esclusivamente alla base dati Oracle e con modalita' da definire su ogni caso particolare, e' vantaggioso l'utilizzo dei database trigger, benche' tale costrutto non sia portabile.
Snapshots
Lo Snapshot e' una copia locale di una tavola remota ed e' utile quando la tavola e' raramente modificata e spesso interrogata da diversi nodi del sistema. Essendo una copia lo snapshot dovra' essere aggiornato periodicamente (il tempo di refresh e' specificato nella creazione).
Le alternative agli Snapshots sono:
Database Triggers che mantengano tavole replicate in diversi nodi del sistema
Copia manuale della tavola sui nodi del sistema usando statements SQL o Import/Export.
Si tratta di una funzionalita' di Oracle 7.0.
Il meccanismo degli snapshot e' di semplice implementazione e gestione. Risulta quindi molto utile in diverse situazioni. Presenta inoltre il vantaggio di non richiedere un accessibilita' continua tra due o piu' database utilizzati con tecniche distribuite.
OCI
Le Oracle Call Interfaces permettono di sviluppare applicazioni che uniscono i vantaggi di un linguaggio non procedurale come l'SQL e i vantaggi di un linguaggio procedurale di terza generazione (C, Cobol, Fortran) oltre che del PL/SQL. Le OCI sono una serie di Application Programming Interfaces che permettono di manipolare i dati di un database Oracle. Librerie che supportano le OCI sono offerte per i piu' diffusi linguaggi di terza generazione. Molti tools Oracle e di terze parti sono stati scritti utilizzando tale interfaccia (Es: SQL*Forms, SQLRouter, ..).
La programmazione a livello di OCI consente vantaggi prestazionali soprattutto in relazione all'allocazione ed al riutilizzo di cursori. La programmazione OCI non e' di semplice utilizzo ne' di facile controllo.
L'utilizzo dell'interfaccia OCI e' cosigliato solo per la scrittura di software particolari in cui i tempi di accesso e l'utilizzo della memoria siano vincoli rilevanti.
E' possibile svolgere diverse attivita' di controllo ed ottimizzazione della base dati. Oracle fornisce alcuni strumenti per effettuare tali attivita'.
In particolare con Oracle il controllo sull'utilizzo degli indici puo' essere effettuato con l'utility EXPLAIN PLAN, con prove dirette in SQL oppure cercando di comprendere la selettivita' delle ricerche effettuate (usando un ragionamento cost based e tenendo conto che Oracle puo' usare sia un ragionamento syntax based che cost based).
I paragrafi successivi riportano alcuni elementi relativi alle utilita' disponibili.
EXPLAIN PLAN
Il comando EXPLAIN PLAN mostra l'esatto percorso compiuto dall'ottimizzatore ORACLE per eseguire uno statement SQL: e' cosi' possibile verificare se vengono adeguatamente sfruttati gli indici presenti.
Il comando EXPLAIN PLAN (applicato a un determinato statement SQL) popola una tavola di servizio da cui e' possibile estrarre le informazioni che interessano.
TRACE
L'SQL trace fornisce le statistiche sull'esecuzione di uno statement SQL:
- i tempi (CPU e elapsed) di parse, execute e fetch
- le letture fisiche e logiche
- il numero di righe processate.
Quando l'SQL trace e' attivato per una sessione, le statistiche di tutti gli statements eseguiti sono scritte in un trace file che, tramite il programma TKPROF, viene trasformato in un file leggibile. Il tracing puo' essere attivato sia sulla singola sessione che per l'intero database. Fare riferimento alla manualistica Oracle per l'abilitazione del tracing.
Statistiche SQL
E' possibile effettuare diversi tipi di selezioni statistiche di controllo della base dati e delle prestazioni di questa. La versione 7.X estende peraltro tale possibilita' offrendo viste sui dati puntuali quali il numero di utenti collegati, i buffer disponibili, .. Le viste dinamiche su cui si basano tali statistiche hanno il prefisso comune V$.
Alcune selezioni statistiche sulle principali viste di sistema sono disponibili nelle directory di Oracle, per un riferimento completo fare riferimento alla manualistica Oracle.