Bisogna subito dire che la recensione di questo testo, edito da
Packt Publishing, è insieme una grande responsabilità e un onore, dato che l'autore è un collega di
Programmazione.it, al suo primo libro, per cui occorre più attenzione del solito, allo scopo di non perdere l'obiettività.
Nella
prefazione l'autore,
Ciro Fiorillo, descrive i contenuti di questo libro, sull'
ottimizzazione delle performance, precisando che l'insieme di ricette in esso contenute non possono essere considerate come proiettili d'argento, da sparare nei momenti critici e aspettarsi che siano infallibili; questo perché nel testo viene mostrato, in realtà, l'approccio corretto a differenti problematiche e occorre impostare la propria attività utilizzando quotidianamente buone pratiche, così come occorre prendere dimestichezza con quello che è un vero e proprio processo, con una fase di analisi, un'ipotesi di soluzione, una fase di verifica post implementazione. Infatti viene avviata una
sessione di tuning, con il suo primo passo che consiste nel definire gli obiettivi che si intendono perseguire. Poi segue una descrizione dei vari capitoli e viene indicato cosa serve per poter lavorare con gli esempi proposti.
Veniamo poi al
target dei lettori, che viene indicato in sviluppatori software, architetti e DBA che stanno iniziando a usare il database di
Oracle. Giudicando solo dai titoli dei capitoli, il target appare sottostimato; alcune argomentazioni sembrano ampiamente varcare la soglia di utilizzatori
beginner di
Oracle, per cui ci si potrebbe spingere a dire che la platea a cui si rivolge questo testo è più ampia di quella indicata. Il paragrafo si conclude con tutta la consueta serie di riferimenti per la ottimale fruizione del testo: font usati, link ai sorgenti degli esempi; e riferimenti alla
post production del libro:
errata corrige, domande, segnalazioni, violazioni.
Nel
primo capitolo si parte con una breve panoramica dei problemi più comuni di performance riscontrabili in ambito applicativo, sia di design che di implementazione di codice. Si prosegue poi esaminando il processo di
tuning (il prestazionale) definito dall'autore che prevede un ciclo di 7 passi, reiterabile. Vengono brevemente descritti tutti i passi e si insiste sulla
baseline, il punto di partenza, la situazione attuale del database, sulla quale avviare il
tuning. Per definire una
baseline e le procedure per collezionare i dati di performance, vengono illustrati i tool messi a disposizione da
Oracle 11g per acquisire dati di funzionamento del DB, così come
OEM (Oracle Enterprise Manager), usato come cruscotto veloce per accedere ai tool. Viene anche esplorato il database che verrà utilizzato come esempio nel libro. Si esaminano quindi, per ogni tool, i passi da seguire per collezionare dati di utilizzo: i primi sono il
data dictionary e le
dynamic views; poi sempre per ogni tool viene spiegato come questi lavorano, ad esempio gli
Statpacks Report e l'
Automatic Workload Repository; come analizzare i dati con l'
Automatic Database Diagnostic Monitor. Si conclude il capitolo un po' troppo carico di informazioni, con un esempio pratico, passo passo, di utilizzo dello
statspack.
Il
secondo capitolo si focalizza sulla buona pratica di pensare all'ottimizzazione delle performance, già a partire dal design dell'applicazione. Qui si inizia a vedere come saranno strutturati i singoli capitoli, come una serie di suggerimenti, illustrati con una lista passo passo di DML e DDL da eseguire, per poi controllare gli effetti dal punto di vista prestazionale (
How to do it); eventualmente questa sequenza operativa viene preceduta da una fase preparatoria (
Getting ready); una parte successiva, invece, spiega cosa sia accaduto eseguendo le istruzioni (
How it works). Infine, per alcuni suggerimenti ci sarà una parte di approfondimento (
There's more). Si parte con un suggerimento (
recipe) sulla gestione delle connessioni client, con
Java, e con la spiegazione delle due configurazioni per la connessione a
Oracle,
dedicate server e
shared server, qualche nota su applicazioni web, e poi una
recipe sul riuso di codice, sempre con un esempio Java, ma con l'estensione del concetto in generale. C'è anche una ricetta per la riduzione del numero di richieste al database tramite l'utilizzo di
stored procedure,
sequence e viste materializzate, con 3 pratici e immediati esempi.
Il successivo suggerimento riguarda la
denormalizzazione del database per aumentare le performance riducendo le
join. Qui viene anche accennato un minimo di teoria. Il seguente paragrafo sulla razionalizzazione dell'utilizzo di SQL dinamico inizia con un esempio che francamente non ho ben capito, a meno che non ci sia un errore; in ogni caso, tale parte si riassume nel semplice avvertimento che sarebbe meglio non utilizzare o limitare una delle feature maggiormente usata dagli sviluppatori per accellerare e semplificare il proprio lavoro. In questo capitolo, il livello dei suggerimenti relativi a scelte nella fase di design è coerente con la platea di non esperti indicata come target.
Il
terzo capitolo, quello più corposo del testo, pari quasi al doppio della lunghezza media dei capitoli, tratta di ottimizzazione delle strutture di memorizzazione dei dati. Spesso dal capitolo più consistente del libro, specialmente se la differenza rispetto agli altri è rilevante, si possono intuire le propensioni dell'autore o l'imprinting che costui voleva dare alla sua opera, e sicuramente la corretta gestione delle strutture di memorizzazione è un tema fondamentale, in generale nella ottimizzazione delle performance, e in particolare nelle intenzioni dell'autore. Si parte con suggerimenti su come evitare la frammentazione di singole righe su più
data block, aumentando la dimensione di questi e del buffer di cache, con tutti i pro e contro. Si continua con il problema della migrazione delle righe, record aggiornati che non entrano più in un singolo
DB block e quindi vengono spostate, con un puntatore nella posizione originale, che rimanda alla nuova posizione. Viene illustrato come rimediare, e anche come prevenire dimensionandolo meglio, il
PCT_FREE. Segue un suggerimento su come utilizzare al meglio i campi LOB, riducendo copie identiche dei dati e comprimendoli. Si esplorano velocemente anche le altre possibi opzioni con questi dati: criptare,
nologging e
nocaching. Poi si passa ad esaminare l'utilizzo degli
indici cluster e degli
hash cluster. Poi un vademecum sugli indici, i
B-tree, i
function-based index, le diverse modalità di utilizzo, con uno sguardo ai piani di esecuzione e al range di convenienza nell'utilizzo degli indici; il
rebuild e la compressione degli indici. Seguono ricette per lo sfruttamento dei
Reverse index e dei
Bitmap index. Il ricco capitolo si conclude con esempi su
Index Organized Table (IOT) e sulla creazione di tabelle partizionate, con quest'ultima parte come semplice illustrazione dei comandi per crearle.
Il
quarto capitolo è dedicato alla diagnosi e soluzione delle problematiche di performance più comuni, derivanti da una non attenta scrittura di codice SQL. La struttura dell'esposizione rimane quella dei capitoli precedenti, con una serie di consigli, illustrati tramite una sequenza di passi. Si torna a suggerire l'utilizzo delle variabili
bind come miglioramento delle performance e anche per evitare rischi di sicurezza come la nota
SQL Injection. Si prosegue con un esempio che mostra come evitare
FTS (Full Table Scan), e sulla gestione dello spazio nei blocchi con diversi esempi incentrati sull'uso degli indici da parte dell'ottimizzatore e sull'opportunità di fare un
index range scan o uno
skip scan index. Si prosegue con un confronto tra operazioni che utilizzano o meno array e
bulk operation, così come
direct path load. Vi sono poi consigli sull'utilizzo delle
join e delle
subquery, e il capitolo si conclude con un esempio su come attivare il
trace delle attività e utilizzare
TKPROF per avere un report di queste.
L'autore mostra, nel
quinto capitolo, alcune problematiche di performance legate alle operazioni di ordinamento attraverso sei differenti
tip. Nel primo suggerimento, decisamente non per principianti, viene proposto come settare alcuni parametri del database per avere un ordinamento in memoria, e non su disco, per le query che ne prevedano uno. Viene quindi presentato come, inserendo un opportuno indice, si possano evitare operazioni di ordinamento su un
FTS. Si prosegue con un esempio sulle query
top-n e le funzioni
RANK() e
DENSE_RANK(); su come ottimizzare il
max,
min,
count e viene spiegato come non abusare dell'
having nelle operazioni di raggruppamento. L'autore sfata il mito che
count(1) sia migliore di
count(*), e aggiunge un consiglio su
union,
minus e
intersect con i loro sostituti più performanti. E' la volta, per chiudere il capitolo, di esaminare alcuni suggerimenti sull'ottimizzazione della gestione dei
tablespaces.
L'ottimizzazione di codice
PL/SQL è l'argomento del
sesto capitolo, che inizia con una riproposizione dell'uso delle variabili
bind e del
BULK COLLECT. Viene poi testato l'uso di
NOCOPY, cioè il passaggio di valori per riferimento, ma senza evidenti miglioramenti di performance. Si passa poi a considerare l'uso intelligente dell'ordine delle condizioni in un
IF, e le motivazioni per evitare funzioni ricorsive. I suggerimenti successivi prendono in considerazione la compilazione nativa di codice
PL/SQL, le funzioni con
RESULT_CACHE introdotte con
Oracle 11g e la possibilità di definire funzioni e procedure
INLINING. Il capitolo termina con un esempio sull'uso di colonne virtuali e alcuni suggerimenti sul miglior uso dei
trigger.
Il
settimo capitolo contiene consigli per indirizzare l'
ottimizzatore di Oracle a scegliere i migliori piani di esecuzione e ottenere, di conseguenza, migliori performance. Dopo qualche riga introduttiva, si inizia con consigli sull'uso di qualche
hint e sulla produzione di statistiche, con vari comandi e parametri. Si prosegue considerando la generazione degli istogrammi e i casi in cui risultano davvero utili. Un suggerimento sulla creazione di
stored outline, per stabilizzare i piani di esecuzione e la feature introdotta con
Oracle 11g —
adaptive cursor sharing —segue un esempio di creazione di un
SQL tuning set e l'utilizzo di
SQL Tuning Advisor, per terminare con la creazione di una
SQL baselines.
Altri 6 suggerimenti su argomenti vari sono presentati nell'
ottavo capitolo: query, DML e caricamento dati. Si inizia con un esempio su come attivare o ampliare la
RESULT CACHE lato client, utilizzabile con le OCI. Il parallelismo è l'argomento del secondo suggerimento, che mostra come l'utilizzo dell'
hint PARALLEL, in una macchina multi-core e una query pesante, migliori decisamente le performance. Si prosegue con il terzo esempio, che mostra come sia molto più veloce un inserimento tramite il
Direct Path Loading, utilizzato anche per comparazione con il successivo
CREATE TABLE AS SELECT. Il quinto suggerimento mostra, tramite una serie di operazioni come sia l'esistenza di indici che la presenza di
trigger comportino un aumento dei tempi di inserimento in tabella; occorre quindi valutare i pro e contro. Nel caso dei
trigger per calcolare un valore in una colonna, viene, quindi, consigliato l'uso di
virtual column. L'ultimo suggerimento racchiude diversi esempi, dal caricamento di dati da un file tramite
SQL Loader, sia in modalità normale che con un metodo diretto, alla creazione e utilizzo di una
external table, per finire con export e import tramite
Data Pump.
Il
nono capitolo regala una serie di consigli che riguardano più la parte infrastrutturale. Si inizia con una breve panoramica sul dimensionamento della
System Global Area (SGA), con l'uso di dynamic performance view e di
OEM (Oracle Enterprise Manager), e la sua componente
Advisor Central. Nel paragrafo successivo viene spiegato come ispezionare la
Library Cache e fornite alcune indicazioni su come questa sia collegata alle performance, mentre di seguito si esamina lo
SHARED POOL, e le sue strutture in memoria, illustrando alcune operazioni per il miglioramento delle performance. Si passa poi ad esaminare la
PGA (Program Global Area) e la
UGA (User Global Area) con il loro
tuning, terminando poi con la
BUFFER CACHE.
Il miglioramento delle performance di I/O è l'argomento del
decimo capitolo: dalla ottimale distribuzione dei vari
online redo log file su dischi separati e gli
archived redo log si arriva alle indicazioni anche sui vari nomi dei processi
Oracle che effettuano operazioni su
data file. Nel secondo consiglio il lettore vedrà come distribuire gli oggetti
Oracle su dischi diversi: tabelle su altri
tablespace o aggiunte di
data file a
tablespace, ma su diversi dischi. Vengono di seguito esaminati i differenti livelli RAID e, per ognuno, indicato quale tipo di file di database memorizzare. Qualche accenno all'utilizzo di operazioni di I/O asincrone, e una panoramica sui
checkpoint e sui
redo log file, con qualche suggerimento di ottimizzazione.
Nell'
undicesimo capitolo si esaminano le problematiche relative alla contesa di risorse tipiche del database. Si inizia con le procedure per individuare dei lock, utilizzando le varie viste
Oracle, e si continua con l'analisi sulle transazioni e la concorrenza, iniziando dai
deadlock, e proseguendo con il
tuning dei
latch. Il suggerimento che segue mostra come, riducendo le risorse richieste, viene minimizzata la contesa dei
latch, ma anche come l'utilizzo delle variabili
bind, riduca il
latch contention.
L'ottima
Appendice A è una lista commentata di 53
Dynamic Performance View, con una breve descrizione e l'indicazione dei campi più utili, mentre l'
Appendice B è una illustrazione di 15 package
Oracle usati per il miglioramento delle performance, con una minima descrizione del package stesso e delle procedure che contiene. L'
indice analitico, fondamentale per questo testo, che chiude la trattazione, è di una dozzina di pagine.
Questo libro, come più volte detto, è un
insieme di suggerimenti, che abbraccia un'ampia varietà di componenti e situazioni, da qui la sua grande e indubbia utilità. Non si avranno panoramiche e introduzioni generali ai vari argomenti, cosa che forse ci si potrebbe aspettare essendo un testo la cui platea dichiarata sarebbe costituita da persone che iniziano a usare
Oracle. Diciamo che forse sussiste una lieve contraddizione tra pubblico inesperto e libri
cookbook, se non altro nel mondo informatico/tecnico. Probabilmente per chi è davvero agli inizi, sarebbe preferibile un testo che introducesse in dettaglio alcuni dei concetti qui solamente toccati, o almeno prevedere un doppio acquisto. Detto ciò sono convinto che questo libro possa essere utile a un pubblico ben più ampio di quello indicato, dato che vi sono in questo ambiente, pluriennali utilizzatori di
Oracle,che non si sono mai addentrati a studiare alcune delle dinamiche ampiamente illustrate in queste pagine.
Come primo libro dell'autore, la scomposizione in suggerimenti avrà certamente facilitato la redazione, ma non va sottovalutata comunque la vastità di argomentazioni trattate, denotata anche dal considerevole numero di pagine, che fanno di questo testo un'opera prima ben riuscita. Ottimo l'inglese, preciso e scorrevole; di enorme valenza, sia le appendici che l'indice analitico, fondamentale per un testo strutturato in consigli.