TRASLOCO
Sempre mosso dalla voglia di allontanarmi da Google e dai suoi servizi, ho finalmente deciso che dopo diversi anni la piattaforma di questo piccolo spazio andava cambiata. Finalmente il blo cambia casa. Se volete trovarmi potete recarvi al nuovo indirizzo

martedì 15 maggio 2012

Sql: Aggiornamento o inserimento in una sola query

  
Quando si scrivono applicazioni che utilizzano un database per il salvataggio dei dati, è sempre importante tenere presente che la velocità è uno dei fattori più influenti per la buona riuscita del nostro lavoro. Bisogna infatti pensare che in ogni banca dati possono essere memorizzati milioni di record che, se analizzati e trattati, possono richiedere tempo e risorse che vengono sottratti ad altre attività che nello stesso momento girano sulla macchina in uso. Proprio per questo motivo quando si lavora su db sql è sempre preferibile demandare ogni tipo di attività al database stesso poiché la sua struttura ed i suoi strumenti sono programmati affinché le operazioni siano il meno dispendiose possibile.

Una delle attività più ricorrenti da effettuare su una serie di dati è il loro aggiornamento (se i dati sono presenti) o il loro inserimento (qualora essi non esistano ancora) all'interno del database in base ad una serie di variabili campione (ad esempio l'imput di un utente in una form). Questo lavoro richiede sicuramente un'estrazione di dati per effettuare un confronto ed un'analisi al fine di capire se eseguire un aggiornamento o un inserimento. Se volessimo analizzare le operazioni da eseguire con una serie di step, rappresentanti un algoritmo, essi si presenterebbero così:

APRO LA CONNESSIONE AL DB
CERCO I DATI NEL DB
SE I DATI SONO PRESENTI:
    AGGIORNA I DATI CON I NUOVI VALORI
ALTRIMENTI:
    INSERISCI I DATI NEL DB
CHIUDO LA CONNESSIONE AL DB

Come si può vedere, nonostante il codice sia il più minimale possibile, esso richiede una serie di passaggi che portano via una notevole quantità di tempo. Basti pensare che se il database in questione contiene 1 milione di record esso verrà (nella migliore delle ipotesi) "percorso" 2 volte (non necessariamente nella sua interezza) e ciò significa analizzare una grande mole di dati. Se a ciò aggiungiamo la complessità dei vari moduli dei diversi linguaggi di programmazione che dovrebbero aiutarci in questo lavoro allora capiamo quanto risparmiare secondi preziosi diventi fondamentale. 

A giungerci in aiuto in questo contesto arriva uno strumento sql davvero molto potente: ON DUPLICATE KEY. Esso ci permette di eseguire le operazioni appena viste sopra (aggiornamento o inserimento) in una sola query senza preoccuparci di estrazioni e confronti. Il suo funzionamento è molto semplice. Esso si prende in carico il compito di analizzare la presenza di una determinata chiave e nel caso essa sia presente aggiornarla altrimenti inserirla. La sintassi si presenta come segue (l'esempio è riferito ad un db MySql):

INSERT INTO tabella (chiave, campo1, campo2, ..., campoN) VALUES (valchiave, val1, val2, ..., valN) ON DUPLICATE KEY UPDATE campo1=val1, campo2=val2, ..., campoN = valN

In pratica la query si occupa di cercare all'interno del db il record in base al valore della chiave primaria (nel nostro caso chiave) qualora esso sia presente verrà aggiornato con i valori della tupla che segue VALUES altrimenti verrà creata una nuova voce con i valori definiti dopo UPDATE. Si noti che nell'esempio che il valore di chiave nel caso di inserimento non è definito poiché il database conterrà una chiave con autoincremento ma qualora (per nostre scelte strutturali) la chiave deve essere definita manualmente la si potrà passare come un qualsiasi altro parametro. La query diventerebbe così:

INSERT INTO tabella (chiave, campo1, campo2, ..., campoN) VALUES (valchiave, val1, val2, ..., valN) ON DUPLICATE KEY UPDATE chiave=valchiave, campo1=val1, campo2=val2, ..., campoN = valN

Grazie all'uso di ON DUPLICATE KEY i vecchi step dell'algoritmo diventano:

APRO LA CONNESSIONE AL DB
ESEGUO QUERY
CHIUDO LA CONNESSIONE AL DB

La scelta di questo strumento si è dimostrata appropriata in un test eseguito di persona. Si è visto, infatti, che confrontando i tempi di esecuzione di uno script python non ottimizzato con db mysql in locale popolato da 96000 record di prova, i due diversi algoritmi (con e senza ON DUPLICATE KEY) hanno portato una differenza di tempo di circa il 15%.