martedì 4 novembre 2008

Mappare le singole proprietà degli oggetti su un database

In questi giorni sto lavorando ad una applicazione PHP che mappa degli oggetti su dei dati che risiedono su un database relazionale. Nulla di nuovo, nulla di sconvolgente, si tratta di un normale mapping ORM. Il problema è che l'applicazione è lenta, anzi lentissima, per quelle che sono le capacità del server e della rete su cui gira.
Il primo passo per me è stato analizzare i log di PostgreSQL (il database server che ospita i dati) per cercare di capire che tipo di query venivano lanciate. Ebbene ho trovato una serie di micro-query ripetute in modo massivo, e analizzando il codice ho trovato che ogni singolo dato di un oggetto veniva sempre riletto dal database ogni volta che veniva acceduto. In sostanza quindi ogni operazione di get forzava un reload del singolo dato dal database, e quindi il traffico di query, tutte piccole e poco ottimizate (e ottimizzabili) diventava enorme. La mappatura ORM prevede quindi di non tenere in memoria le proprietà di un oggetto ma di ricaricarle ogni volta che queste vengano richieste direttamente dal database. E' evidente che in quest'ottica i singoli metodi get non possono essere ottimizzati, ma si può procedere ad una velocizzazione delle operazioni per metodi getAll su più proprietà dello stesso oggetto. In sostanza si tratta di creare metodi wrapper attorno a più operazioni di get, facendo eseguire però una singola operazione sul database. Se ad esempio si hanno i metodi getNome e getCognome, considerando che nell'applicazione molto spesso occorrono entrambi i dati, si può costruire una funzione getNomeCognome che restituisca un array con entrambi i dati. Al suo interno la funzione non farà affidamento sui due servizi getNome e getCognome, perché questo significherebbe creare due query sul database, bensì effettuerà una query unica verso il database. Sfruttando quindi questi metodi get-combinati si possono ottenere tutti i dati che servono al flusso dell'applicazione con query uniche e quindi riducendo il traffico di rete e la latenza del database.

Nessun commento: