NVMe o SSD SATA su VPS: cambia davvero qualcosa?
NVMe offre più IOPS e meno latenza, ma su un VPS contano hypervisor e vicini. Scopri cosa misurare con fio e quando la differenza è minima.
NVMe è importante su un VPS?
NVMe è importante su un VPS quando il software esegue molte operazioni di lettura e scrittura di piccole dimensioni e attende il completamento di ciascuna. Cambia molto poco per un sito che distribuisce pagine memorizzate nella cache o per un programma che trascorre il proprio tempo in attesa della rete. Il supporto di archiviazione è un fattore. Il limite effettivo dipende dall’hypervisor che precede il disco e dagli altri guest che condividono lo stesso host.
Cosa cambia NVMe e cosa non cambia
NVMe (non-volatile memory express) non è un tipo di memoria flash. È il protocollo e la connessione usati per accedere alla memoria flash. Un dispositivo NVMe usa le linee PCIe (peripheral component interconnect express) e comunica tramite NVMe. Un SSD SATA (serial ATA) usa un collegamento SATA e comunica tramite AHCI (advanced host controller interface). I chip di memoria che contengono i dati possono essere identici in entrambi i casi.
Le differenze sono due e riguardano entrambe il percorso dei comandi, non lo storage in sé.
Code. AHCI fornisce al kernel una coda di comandi che contiene 32 comandi. NVMe consente migliaia di code, in pratica una per ogni core della CPU, ciascuna molto più profonda di 32. Un processo che legge un blocco alla volta non può notare questa differenza. Un database con 64 letture in sospeso sì: su SATA la 33a richiesta attende uno slot nella coda prima che il dispositivo la veda, mentre il dispositivo NVMe le accetta tutte e le elabora contemporaneamente.
Larghezza del collegamento. Un collegamento SATA III funziona a 6 Gbit/s, pari a circa 550 MB/s di dati effettivi dopo l'overhead del protocollo. Questo è un limite massimo fisso, indipendentemente dalla memoria flash collegata. Quattro linee PCIe trasferiscono diversi gigabyte al secondo, quindi il collegamento non è più il fattore limitante.
La latenza è l'aspetto su cui le aspettative sono generalmente errate. Con una profondità della coda pari a 1, cioè con una sola richiesta in elaborazione, un SSD SATA risponde a una lettura 4k in circa 100-150 microsecondi. NVMe risponde in circa 80-100 microsecondi. Entrambi sono veloci e nessun carico di lavoro noterà la differenza per una singola richiesta. La differenza emerge con la concorrenza. La profondità della coda, cioè il numero di richieste in elaborazione contemporaneamente, determina se i due supporti si comportano in modo simile o molto diverso.
Lo storage a blocchi di rete appartiene a una terza categoria, con caratteristiche fisiche diverse. Una scrittura attraversa la rete fino a un cluster di storage e viene confermata solo quando il cluster la contiene; per questo la latenza si misura in millisecondi anziché in microsecondi. In cambio di questa latenza si ottiene la durabilità: il volume sopravvive all'host a cui è collegato e può essere sottoposto a snapshot e ridimensionato.
Valori tipici pubblicati: NVMe, SSD SATA e storage di rete
The data behind this chart
[
{
"disk": "Local NVMe SSD",
"iops_4k_read": "184,000",
"p99_latency_ms": 0.4,
"seq_read_mbps": "3,400"
},
{
"disk": "Local SATA SSD",
"iops_4k_read": "90,000",
"p99_latency_ms": 1.2,
"seq_read_mbps": "550"
},
{
"disk": "Network block storage",
"iops_4k_read": "12,500",
"p99_latency_ms": 6.5,
"seq_read_mbps": "250"
}
]Un dispositivo NVMe locale viene comunemente indicato con 184,000 IOPS di lettura casuale 4k (operazioni di input/output al secondo) a una profondità della coda pari a 32. Lo stesso test su un SSD SATA viene indicato intorno a 90,000, limitato dalla singola coda AHCI e dal collegamento a 6 Gbit/s. Lo storage a blocchi di rete è generalmente limitato dal provider e non dall'hardware; 12,500 è un limite massimo documentato comune.
La latenza esprime lo stesso risultato nell'unità percepita dagli utenti. La latenza di lettura p99, cioè quella del 1% più lento delle richieste, è di circa 0.4 ms su NVMe locale e 1.2 ms su SATA. Se nel percorso è presente una rete, il valore diventa 6.5 ms, oltre dieci volte il valore di NVMe.
Le letture sequenziali mostrano la differenza maggiore, ma sono anche il dato meno utile: 3,400 MB/s contro 550 MB/s. Quasi nulla su un server legge un file di grandi dimensioni dall'inizio alla fine alla massima velocità. La colonna delle operazioni casuali e quella della latenza descrivono ciò che fanno realmente un database, una coda di posta o un gestore di pacchetti.
Da dove provengono questi valori e perché i tuoi saranno diversi
Le 3 righe sono valori riportati nelle schede tecniche dei vendor per i dispositivi locali e limiti documentati per volume per lo storage di rete, aggiornati a luglio 2026 e arrotondati. Si basano su una dimensione dei blocchi di 4k, letture casuali, una profondità della coda pari a 32 e un singolo job, ovvero il tipo di test pubblicato dai vendor. Il tuo VPS è un guest su un host condiviso, quindi lo stesso test sul tuo sistema normalmente restituisce un valore inferiore, che varia tra un'esecuzione e l'altra. Interpreta queste righe come indicazione della differenza tra le tre classi, non come un obiettivo da raggiungere.
Quali carichi di lavoro risentono del disco
Una regola spiega tutti questi casi: un carico di lavoro risente del disco solo quando deve attendere il disco. Linux conserva nella RAM i dati dei file usati di recente, nella page cache, quindi la seconda lettura di un file non raggiunge mai lo storage. Se il working set, cioè i dati effettivamente in uso, entra nella RAM, dopo il primo passaggio le letture diventano letture dalla memoria. Le scritture sono diverse. Qualsiasi scrittura che l'applicazione scarica con fsync() deve trovarsi nello storage stabile prima che l'applicazione possa continuare.
Operazioni che eseguono il commit. PostgreSQL, MySQL e SQLite chiamano fsync() o fdatasync() durante il commit, e ogni commit attende la risposta del dispositivo. Il tasso di commit di una connessione è quindi determinato dalla latenza di scrittura, non dalla larghezza di banda. Un dispositivo che esegue il flush in 0.2 ms consente molti più commit al secondo rispetto a uno che impiega 5 ms, e nessun aumento del throughput può cambiare questo risultato. MySQL lo indica nel log degli errori quando il flush non riesce a tenere il passo:
[Note] InnoDB: page_cleaner: 1000ms intended loop took 4589ms. The settings might not be optimal.PostgreSQL lo segnala nelle righe relative ai checkpoint, dove un valore sync= elevato indica che il flush è stato lento:
LOG: checkpoint complete: wrote 8192 buffers (25.0%); write=27.694 s, sync=11.207 s, total=39.001 sOperazioni che accedono a molti file piccoli. Ogni file richiede operazioni sui metadati che una singola lettura sequenziale di grandi dimensioni non richiede. npm install, git clone di un repository di grandi dimensioni, l'estrazione di immagini di container, un archivio di posta Maildir e un backup che percorre un albero di grandi dimensioni trascorrono il tempo in accessi casuali di piccole dimensioni. Un job di backup restic su un VPS legge e calcola l'hash di ogni file che non ha già visto, quindi il tempo reale di un backup di un milione di file segue da vicino la latenza delle letture casuali. Lo stesso vale per du -sh, che legge solo i metadati.
Anche i database che superano la capacità della RAM rientrano in questa categoria. Quando l'indice non entra più nella page cache, ogni ricerca diventa una lettura casuale e il disco torna a essere un elemento critico del percorso.
Quali carichi di lavoro non risentono del disco
Un blog o il sito di una piccola azienda. Le pagine sono piccole, la cache delle pagine le contiene tutte dopo la prima richiesta e il limite è rappresentato dalla CPU necessaria per il rendering o dalla larghezza di banda per le risorse. Uno stack LAMP su Ubuntu 24.04 che serve un sito con poco traffico esegue quasi nessuna operazione di I/O su disco dopo il caricamento della cache.
Streaming multimediale. Uno stream 4K a 40 Mbit/s legge 5 MB/s. Dieci stream leggono 50 MB/s, una velocità che anche lo storage a blocchi di rete gestisce senza difficoltà. Un server multimediale Jellyfin su un VPS è limitato dalla larghezza di banda in uscita disponibile sulla rete e dalla CPU durante la transcodifica, non dal supporto di archiviazione.
Inferenza locale di modelli. Eseguire Ollama su un VPS per ospitare autonomamente un LLM legge il file del modello una volta, quindi lavora nella RAM. NVMe riduce il tempo di caricamento di un modello da 20 GB da minuti a secondi. Non modifica il numero di token al secondo, che dipende dalla larghezza di banda della memoria e dalla CPU.
Qualsiasi attività in attesa di un servizio esterno. Un worker che impiega 800 ms per processo per una richiesta HTTP non diventa più veloce con un disco migliore.
Perché l'hypervisor è importante quanto il supporto
Non si comunica mai direttamente con il dispositivo. Si comunica con un disco virtuale presentato dall'hypervisor, in genere tramite virtio, e diverse decisioni a questo livello contano più della differenza tra NVMe e SATA.
Il supporto non è visibile dall'interno del guest. lsblk -d -o NAME,ROTA,SIZE,MODEL mostra vda con un modello vuoto, perché virtio non trasferisce l'identità dell'unità. cat /sys/block/vda/queue/rotational restituisce ciò che l'hypervisor dichiara, quindi un valore pari a 0 non dimostra che il supporto sia flash. nvme list, incluso nel pacchetto nvme-cli, nella maggior parte dei VPS non elenca nulla anche quando l'host contiene molti dischi NVMe, perché il disco è un dispositivo virtio e non un dispositivo NVMe. Un piano che indica NVMe descrive in genere i dispositivi presenti sull'host. Il volume può comunque essere collegato tramite rete.
La modalità cache dell'host modifica i risultati più del supporto. Con la cache writeback attiva sull'host, una fsync() del guest può restituire il controllo non appena l'host ha i dati nella propria RAM. Questo produce un risultato di benchmark che nessun dispositivo fisico potrebbe raggiungere. Significa anche che un arresto anomalo dell'host può causare la perdita di scritture che il database considera sicure. Con la modalità cache none, i risultati sono inferiori ma attendibili.
Limiti e crediti burst. Molti provider limitano gli IOPS per volume o per piano e molti volumi di rete usano una disponibilità burst. Una disponibilità burst è un insieme di crediti: il volume funziona velocemente finché i crediti sono disponibili, poi passa a una velocità di base molto più bassa. Il sintomo è facile da riconoscere. Un'importazione o un ripristino procede rapidamente per diversi minuti, poi rallenta bruscamente e rimane lento, senza modifiche alla configurazione. I crediti sono esauriti.
I vicini. Su un host condiviso, la latenza del disco varia in base alle operazioni eseguite dagli altri guest. Per questo è necessario eseguire le misurazioni più di una volta. Eseguire lo stesso test al mattino e di nuovo alla sera, quindi confrontare la variazione. Su un host occupato, la differenza tra due esecuzioni sullo stesso volume è spesso maggiore della differenza dichiarata tra due supporti.
Come misurare lo spazio su disco effettivamente disponibile sul VPS
Installare fio, il benchmark standard per l'IO, ed eseguire la misurazione. Prima, tre avvertenze. Il test crea un file, quindi usa spazio su disco e viene conteggiato in qualsiasi limite IOPS incluso nella fatturazione. Mantenere brevi le esecuzioni. Non eseguire il test con una profondità della coda massima su un volume che gestisce traffico in tempo reale, perché si entra in competizione con la propria applicazione.
sudo apt update && sudo apt install -y fio ioping sysstat
cd /var/tmpLettura casuale con profondità della coda pari a 32, che è il valore dichiarato dai provider:
fio --name=randread --filename=fio.test --size=1G --bs=4k --rw=randread \
--ioengine=libaio --direct=1 --iodepth=32 --numjobs=1 \
--runtime=30 --time_based --group_reportingLa riga importante inizia con read:
read: IOPS=184k, BW=719MiB/s (754MB/s)(21.1GiB/30001msec)--direct=1 bypassa la cache delle pagine del guest, quindi il risultato descrive il dispositivo invece della RAM. Se si omette, si misura la memoria, che restituisce un valore irraggiungibile per qualsiasi disco. Usare --size=4G o un valore maggiore se lo spazio disponibile lo consente, perché un file da 1G può rimanere interamente nella cache dell'host e rendere il risultato più favorevole.
La profondità della coda pari a 1 mostra la latenza effettiva, cioè quella percepita da un processo a thread singolo:
fio --name=lat --filename=fio.test --size=1G --bs=4k --rw=randread \
--ioengine=libaio --direct=1 --iodepth=1 --runtime=30 --time_basedIl test dei commit prevede il comportamento del database. Scrive 4k e chiama fdatasync() dopo ogni scrittura, quindi la velocità riportata include il flush:
fio --name=commit --filename=fio.test --size=1G --bs=4k --rw=randwrite \
--ioengine=psync --fdatasync=1 --runtime=30 --time_based
rm -f fio.testIl valore IOPS risultante è vicino al numero massimo di piccole transazioni al secondo che una connessione al database può eseguire con commit, perché un commit attende lo stesso flush.
Per un campione rapido senza fio:
ioping -c 20 .--- . (ext4 /dev/vda1) ioping statistics ---
19 requests completed in 4.13 ms, 76 KiB read, 4.60 k iops, 17.9 MiB/s
min/avg/max/mdev = 174.2 us / 217.6 us / 386.1 us / 51.3 usIl valore mdev, la deviazione media, è importante quanto la media. Una deviazione elevata su un sistema inattivo indica che il backend di archiviazione è condiviso e sotto carico.
Come leggere il risultato
A luglio 2026, queste sono interpretazioni ragionevoli per un piccolo VPS. Decine di migliaia di IOPS di lettura casuale 4k con una profondità della coda pari a 32, e una latenza con profondità della coda pari a 1 inferiore a circa 0.3 ms, sono coerenti con lo storage flash locale. Una latenza di diversi millisecondi con profondità della coda pari a 1 indica un percorso di rete, indipendentemente dal nome del piano. Le letture sequenziali che si fermano vicino a 550 MB/s sono tipiche di un collegamento SATA. Un valore molto superiore a quello ottenibile da un singolo dispositivo indica che nel percorso è presente una cache, quasi sempre sull'host.
Per vedere in che modo il carico di lavoro attivo utilizza il disco:
iostat -x 1 3
vmstat 1 5
cat /proc/pressure/ioNell'output di iostat -x, leggi r_await e w_await, i millisecondi medi di attesa di una richiesta, e aqu-sz, la lunghezza media della coda. Ignora %util su un disco virtuale. Indica la percentuale di tempo in cui almeno una richiesta era in corso, ma non fornisce informazioni sulla saturazione di un dispositivo che gestisce molte richieste contemporaneamente; quindi, un valore di %util pari a 100 insieme a un valore di r_await pari a 0.2 ms indica un disco occupato ma in condizioni normali. In vmstat, la colonna wa indica la percentuale di tempo CPU trascorsa in attesa di operazioni IO. Se /proc/pressure/io è presente nel kernel, il relativo valore some avg10= indica la quota degli ultimi 10 secondi durante la quale almeno un'attività era bloccata in attesa di IO; questo è l'indicatore più diretto per stabilire se lo storage è il collo di bottiglia.
Come si presenta un VPS limitato dal disco
Un load average elevato con CPU inattiva e un valore elevato di wa in vmstat indicano che i processi sono in coda in attesa del disco. Il segnale più chiaro del kernel è questo messaggio in dmesg -T:
INFO: task jbd2/vda1-8:194 blocked for more than 120 seconds.La riga viene visualizzata perché un thread del kernel ha atteso oltre due minuti la risposta dello storage; per questo il watchdog delle attività bloccate ha registrato l'evento. jbd2 è il thread del journal di ext4. Questo indica che l'intero filesystem era in attesa, non un singolo programma che si comportava in modo anomalo. Su un VPS, di solito il problema riguarda il backend di storage o l'esaurimento del limite di IOPS.
Anche i sintomi dell'applicazione seguono lo stesso schema. Il tempo di risposta mediano rimane accettabile, mentre le richieste più lente formano una coda lunga, perché solo le richieste che accedono al disco ne subiscono il costo. apt upgrade rimane su Unpacking per minuti, perché dpkg esegue il flush durante la scrittura. git status in un repository di grandi dimensioni richiede alcuni secondi. Si tratta di costi legati ai metadati e al flush, quindi una maggiore larghezza di banda non risolverebbe il problema.
Cosa fare quando il disco è il limite
Acquistate RAM prima degli IOPS. Se il working set rientra nella page cache, le letture non raggiungono più il disco. Raddoppiare la memoria spesso offre prestazioni migliori rispetto al passaggio a una classe di storage più veloce e, di solito, costa meno.
Riducete il numero di flush, quando i dati lo consentono. In PostgreSQL, synchronous_commit = off consente al commit di restituire il controllo prima che la scrittura venga completata sul disco. Se il server si arresta, potete perdere l'ultima frazione di secondo delle transazioni. Il database non viene danneggiato, perché il write-ahead log viene comunque scritto in ordine. Questo compromesso è adatto a una copia per l'analisi, ma non ai pagamenti. In MySQL, innodb_flush_log_at_trx_commit = 2 applica lo stesso compromesso.
Raggruppate i file piccoli. Un trasferimento o un backup di un milione di file piccoli è dominato dal costo per file. Per questo, su storage con latenza elevata, è più veloce creare prima un archivio e trasferire un unico flusso, invece di copiare l'albero file per file.
Mantenete attivo il discard sui volumi thin. Con lo storage thin provisioned, il backend non sa che un blocco è libero finché il filesystem non lo comunica. Un volume che non esegue mai il trim perde lentamente prestazioni di scrittura. Ubuntu fornisce un timer settimanale:
systemctl status fstrim.timer
sudo fstrim -avfstrim -av stampa i byte sottoposti a trim per ogni punto di mount. Un messaggio che indica che l'operazione discard non è supportata significa che il disco virtuale non inoltra il discard all'host. Non c'è quindi nulla da correggere.
Evitate di ottimizzare lo scheduler I/O. Su un disco virtio, cat /sys/block/vda/queue/scheduler mostra di solito già none, mentre la pianificazione effettiva avviene sull'host, a cui non avete accesso. Evitate anche noatime: Ubuntu esegue il mount con relatime per impostazione predefinita, evitando già quasi tutte le scritture di atime.
Scelta del piano
Paga per NVMe quando sul server eseguono un database, un mail server, un CI runner o una build con molti pacchetti. Non pagare un sovrapprezzo per un sito web memorizzato nella cache o per un'applicazione il cui tempo di esecuzione è assorbito da chiamate esterne. Se non sei sicuro, probabilmente il disco non è il tuo limite, perché la maggior parte dei carichi di lavoro su VPS di piccole dimensioni esaurisce prima la RAM o la larghezza di banda.
Esegui le misurazioni il primo giorno, mentre segui i primi dieci minuti su un nuovo VPS, e conserva l'output in un file. Una baseline ti permette in seguito di dimostrare che l'host è diventato più lento, invece di attribuire il problema al tuo codice. Preferisci provider che dichiarano per iscritto la classe di storage e l'eventuale limite di IOPS. Se un piano indica NVMe e una lettura con queue depth 1 richiede 4 ms, stai usando storage di rete su un host dotato di NVMe. È un prodotto legittimo da vendere, ma non è lo stesso prodotto che stai acquistando.
FAQ
NVMe è sempre più veloce di un SSD SATA su un VPS?
No. Con una profondità della coda pari a 1, i due dispositivi hanno prestazioni simili: circa 80-150 microsecondi per una lettura 4k. Un programma a thread singolo non rileva la differenza. NVMe offre prestazioni superiori quando sono presenti molte richieste simultanee, perché AHCI fornisce una coda con una profondità di 32 comandi, mentre NVMe fornisce migliaia di code più profonde. Su un host condiviso, il carico degli altri guest può influire sulla latenza più del tipo di supporto. Misura quindi il tuo volume con fio invece di basarti sul nome del piano.
Come posso verificare se il mio VPS usa davvero NVMe?
Non puoi verificarlo direttamente, perché virtio nasconde il dispositivo fisico. lsblk mostra vda senza una stringa del modello, nvme list non restituisce nulla e /sys/block/vda/queue/rotational riporta solo le informazioni pubblicizzate dall'hypervisor. Misura invece il comportamento. Una lettura casuale 4k con profondità della coda pari a 1 e latenza inferiore a circa 0.3 ms indica un flash locale. Una latenza di diversi millisecondi indica che nel percorso è presente un passaggio attraverso la rete. Letture sequenziali che si fermano vicino a 550 MB/s indicano un collegamento SATA.
NVMe rende più veloce il caricamento del mio sito?
Di solito no. Dopo la prima richiesta, Linux serve i file dalla page cache in RAM, quindi il disco non viene utilizzato. Su un VPS di piccole dimensioni, la velocità della pagina è normalmente limitata dal tempo di CPU dell'applicazione e dalla larghezza di banda. Il disco torna a essere un elemento critico se il sito scrive a ogni richiesta, per esempio nel caso di un carrello basato su un database che esegue spesso il commit, perché ogni commit attende il completamento di un flush.
Qual è un buon risultato di fio per un VPS?
A luglio 2026, un VPS di piccole dimensioni con flash locale restituisce in genere decine di migliaia di IOPS per letture casuali 4k con profondità della coda pari a 32, con una latenza inferiore a 0.3 ms con profondità della coda pari a 1. Lo storage a blocchi di rete restituisce in genere alcune migliaia di IOPS, con una latenza di alcuni millisecondi. Esegui il test 3 volte in orari diversi. Una forte variazione tra le esecuzioni è più indicativa della media, perché mostra quanto gli altri guest sull'host influenzano le tue prestazioni.
Devo collocare il database su uno storage a blocchi di rete?
Puoi farlo e molti servizi gestiti lo fanno, ma il percorso di commit ne risente. Ogni flush attraversa la rete, quindi una singola connessione esegue meno transazioni di piccole dimensioni al secondo rispetto a quanto farebbe con un flash locale. In cambio, ottieni una durabilità che sopravvive all'host. Se scegli lo storage di rete per un database con molte operazioni di scrittura, raggruppa il lavoro in transazioni più grandi, in modo che un numero inferiore di flush trasferisca più righe.