PostgreSQL e MySQL non hanno un vincitore assoluto nelle prestazioni. Il throughput e la latenza acquistano significato solo insieme al tipo di transazioni, alle garanzie richieste e alla configurazione: una rassegna dei confronti per carico distingue i meccanismi documentati dalle cifre dichiarate dai vendor e rinuncia a una classifica numerica unica. Per scegliere un database contano le operazioni che l’applicazione esegue davvero, non il valore aggregato più alto.
C’è una differenza già nelle impostazioni iniziali. La documentazione di PostgreSQL sull’isolamento indica Read Committed come livello predefinito: due SELECT successive nella stessa transazione possono vedere risultati diversi dopo una modifica confermata da un’altra transazione. Per InnoDB, il manuale di MySQL indica Repeatable Read: le letture coerenti della transazione condividono lo snapshot stabilito dalla prima lettura. Perciò una prova eseguita con entrambi i valori predefiniti può confrontare anche garanzie di visibilità diverse.
Perché l’isolamento può cambiare il risultato
Il livello di isolamento determina quali modifiche concorrenti una transazione può osservare e influisce sul modo in cui alcune operazioni acquisiscono blocchi. La differenza diventa rilevante quando il carico comprende letture ripetute, aggiornamenti delle stesse righe o ricerche per intervallo. In questi casi il tempo di risposta può includere attese e nuovi tentativi, oltre al lavoro necessario per eseguire la query.
Si consideri un esempio ipotetico: una transazione legge l’elenco degli ordini aperti, un’altra inserisce un ordine e conferma, poi la prima ripete la lettura. Con Read Committed la seconda SELECT può includere il nuovo ordine; con una lettura coerente in Repeatable Read continua a usare lo snapshot precedente. Contare soltanto le transazioni completate al secondo nasconderebbe questa differenza nel risultato restituito all’applicazione.
Allineare il nome del livello è necessario per una prova mirata, ma non rende automaticamente identiche le implementazioni. InnoDB cambia anche le strategie di blocco delle letture con FOR UPDATE, degli UPDATE e dei DELETE secondo il livello scelto e la forma della ricerca. Per un carico concorrente, una ricerca su chiave unica e una scansione di intervallo possono quindi avere profili di attesa diversi. Il test deve conservare la stessa logica applicativa e registrare il livello effettivamente usato da ciascuna connessione.
Una prova riproducibile parte dalle transazioni
La base è uno scenario funzionalmente equivalente: stessa classe di hardware, stessa quantità e distribuzione dei dati, stesso rapporto tra letture e scritture e transazioni che compiono le medesime operazioni. Anche la dimensione del dataset rispetto alla memoria conta. Se quasi tutte le letture sono servite dalla cache in una prova, il risultato risponde a una domanda diversa da quella posta da un’applicazione che accede spesso al disco.
Gli schemi e gli indici devono soddisfare gli stessi requisiti di ricerca e ordinamento, pur potendo essere progettati in modo diverso per i due motori. Copiare meccanicamente la struttura di un indice può favorire un’implementazione senza rappresentare una scelta realistica. Occorre invece conservare le query, esaminare quali indici ciascun motore usa e includere nel carico il costo delle scritture che li mantengono aggiornati.
La matrice della prova deve riportare versioni, risorse assegnate, client concorrenti, durata, livello di isolamento e impostazioni di durabilità. Una transazione considerata conclusa prima che la scrittura soddisfi la garanzia di persistenza richiesta non va confrontata direttamente con una transazione sottoposta a una garanzia più forte. Vanno dichiarati anche gli eventuali pool di connessioni, il periodo di riscaldamento della cache e il criterio usato per contare transazioni fallite o ripetute.
Il manuale di pgbench descrive uno script predefinito ispirato a TPC-B e la possibilità di usare script personalizzati; tra i risultati riportati compaiono transazioni al secondo, latenza e fallimenti. Lo script predefinito non rappresenta automaticamente un negozio online o un gestionale. Per il confronto fra motori servono operazioni equivalenti e la stessa definizione di transazione completata: il generatore di carico, da solo, non stabilisce l’equivalenza.
Throughput, latenza e concorrenza raccontano cose diverse
Il throughput misura quante transazioni si completano nell’unità di tempo, mentre la latenza descrive quanto attende una singola operazione. Un valore complessivo può migliorare anche quando le richieste più lente peggiorano. Per questo è utile riportare la distribuzione dei tempi insieme alla quota di operazioni fallite, ritentate o rimaste in attesa di un blocco.
I risultati vanno separati per tipo di lavoro. Una lettura tramite chiave primaria percorre un cammino diverso da una join con aggregazione; inserire nuove righe è diverso dall’aggiornare ripetutamente le stesse. Aumentando i client, il punto in cui la latenza cresce più rapidamente del throughput segnala un limite da interpretare alla luce di CPU, accessi ai dati, blocchi e connessioni. Senza questa distinzione, un totale favorevole può nascondere proprio l’operazione più importante per l’applicazione.
Conta inoltre il tempo di osservazione. Un picco breve può non mostrare gli effetti di scritture sostenute, manutenzione e contesa sulle righe più richieste. Una prova utile registra sia il comportamento a carico ordinario sia quello durante la pressione prevista, mantenendo dichiarate le condizioni. Il confronto riguarda due configurazioni capaci di svolgere lo stesso lavoro, non necessariamente due testi SQL identici.
Quale requisito orienta la scelta
Quando le prestazioni sono comparabili entro i limiti richiesti, la decisione può partire dalla parte del sistema più difficile da soddisfare:
- OLTP con transazioni brevi: misurare il mix reale di letture, inserimenti e aggiornamenti, comprese le righe contese. Il risultato più utile è la latenza delle transazioni importanti al livello di concorrenza previsto, insieme ai fallimenti e ai nuovi tentativi.
- Dati geografici: includere PostgreSQL con PostGIS se le interrogazioni spaziali sono centrali. La guida di PostGIS agli indici spaziali descrive l’uso di GiST con funzioni come ST_Intersects; la prova deve usare le geometrie e le ricerche richieste dall’applicazione.
- Campi JSON: distinguere i percorsi di ricerca stabili dai filtri variabili su molti attributi. Valutare insieme il tempo delle letture, gli indici necessari e il costo degli aggiornamenti, anziché misurare una sola query favorevole.
- Sharding: considerare la soluzione completa. Il throughput di una singola istanza non rappresenta il lavoro aggiuntivo di instradamento, migrazione dei dati, query tra partizioni e ripristino.
Infine pesano le competenze operative disponibili: progettare indici, diagnosticare blocchi, gestire backup e aggiornamenti è parte del costo della scelta. Se entrambi i motori rispettano gli obiettivi del carico reale, un piccolo vantaggio in un test sintetico può contare meno della capacità del team di mantenere nel tempo la configurazione misurata.
Leggi anche:
#Adessonews seleziona nella rete articoli di particolare interesse.
Se vuoi leggere l’articolo completo clicca sul seguente link




