Un modulo che in una rete locale compare in meno di un secondo impiega cinque secondi su una VPN, mentre una copia di file sullo stesso collegamento va a piena velocità. La differenza non è la larghezza di banda. Il modulo attende una sequenza di risposte e paga l'andata e ritorno completa a ogni passo, mentre la copia di file tiene i byte in movimento di continuo. Contate queste attese prima di toccare la linea di accesso.

Il sintomo è una schermata, non una query

Ogni query di quella schermata può essere veloce e la schermata può restare lenta, perché il totale è la somma delle attese e non la somma dei tempi di esecuzione. Un'istruzione che viene eseguita in due millisecondi costa comunque un'andata e ritorno completa quando il client deve riceverne il risultato prima di inviare la successiva. Su un percorso con quaranta millisecondi di latenza, cento chiamate dipendenti si sommano a circa quattro secondi prima che inizi qualsiasi lavoro di disegno. Questa aritmetica è un modello dell'attesa, non una misura del vostro collegamento.

Per questo un test di velocità sembra innocente. Il trasferimento massivo misura la portata, un modulo chiacchierone misura la latenza, e una VPN può essere ottima in una cosa e ordinaria nell'altra. Diagnosticare la schermata significa quindi misurare la schermata e non il collegamento.

Registrate il tempo da un capo all'altro di un'azione utente prima di cambiare qualcosa. Quel numero è l'unica linea di base che può dirvi se una correzione successiva ha funzionato.

Contate le attese sequenziali in un'azione utente

Misurate nel client invece di indovinare. In psql, \timing on stampa il tempo trascorso di ogni istruzione, e EXPLAIN (ANALYZE, BUFFERS) mostra quanto di quel tempo il server ha realmente speso nel lavoro.

La differenza fra questi due numeri è il vostro sovraccarico di rete e di client. Se un'istruzione viene eseguita in due millisecondi e il client ne registra sessanta, i cinquantotto rimanenti sono viaggio ed elaborazione locale, e nessun indice li eliminerà. Ripetete questo confronto per ogni istruzione emessa dalla schermata e sommate le differenze invece dei tempi di esecuzione.

Annotate il risultato come conteggio delle attese sequenziali. È la grandezza che le due sezioni seguenti possono ridurre, ed è un numero su cui potete discutere con le prove.

Raggruppate le chiamate indipendenti, conservate le dipendenti

Due istruzioni che non leggono i risultati l'una dell'altra possono viaggiare insieme ed essere raccolte una sola volta, il che trasforma due attese in una. Due istruzioni in cui la seconda ha bisogno del valore della prima non possono, perché la dipendenza è reale e raggrupparle cambierebbe ciò che fa il programma. Dividete le chiamate in questi due mucchi prima di riscrivere qualsiasi cosa, e la dimensione di ciascun mucchio vi dice che cosa è possibile.

Il lavoro basato su insiemi elimina le attese più a fondo del raggruppamento. Una query che restituisce le righe che un ciclo recuperava una alla volta elimina il ciclo e anche gli andirivieni. Cercate prima il ciclo, perché di solito è il guadagno maggiore e la modifica più facile da rivedere.

Un lotto deve comunque preservare la gestione degli errori e i confini delle transazioni. Concatenare istruzioni non correlate in un'unica stringa non è un'ottimizzazione sicura, e un lotto che nasconde un'istruzione fallita dietro un invio riuscito è peggio delle attese che ha risparmiato.

Riusate le connessioni prima di comprare larghezza di banda

Una nuova connessione costa la risoluzione dei nomi, una stretta di mano TCP, la negoziazione TLS e l'autenticazione, e su un percorso ad alta latenza ciascuno di questi è un altro andirivieni prima che la prima query parta. I pool di connessioni esistono per pagare questo costo una volta per processo invece di una volta per chiamata.

In ADO.NET, chiudere o eliminare una connessione del pool la restituisce per il riuso invece di aprirne una nuova fisica, quindi lo schema che sembra una perdita è spesso l'uso corretto. Verificate che il pool sia davvero in uso invece di presumerlo: registrate la creazione delle connessioni fisiche, oppure osservate il numero di sessioni sul server mentre la schermata gira. Le linee guida sulle prestazioni di SQL dicono la stessa cosa sulla riduzione degli andirivieni e sul raggruppamento delle chiamate ad hoc frequenti, con esempi specifici del servizio che dovreste trasferire nel vostro deployment.

Il pooling elimina il costo di configurazione e lascia intatte le attese sequenziali delle query. È un prerequisito per una misurazione pulita, non una correzione di per sé.

Valutate lo spostamento dell'esecuzione più vicino ai dati

Eseguire l'applicazione vicino al database sostituisce molti scambi remoti con il database con un'unica sessione di visualizzazione remota. Per un carico chiacchierone può essere un cambiamento importante, ed è un cambiamento operativo quanto un cambiamento di prestazioni: gestione delle sessioni, controllo degli accessi, distribuzione del software ed esperienza utente si spostano tutti con l'applicazione.

Misurate l'interfaccia reale e i dati che trasferisce prima di supporre che una direzione sia più veloce. Una sessione desktop remota sposta pixel, e una schermata con grafica densa può comportarsi peggio sullo stesso percorso delle query che ha sostituito, soprattutto quando il client ridisegna di continuo.

Poi ripetete l'azione originale e confrontate tre numeri: attese sequenziali, volume dei risultati e tempo di completamento da un capo all'altro. Un miglioramento che cambia il compito utente misurato preservando la correttezza dei dati e la politica di accesso è quello che vale la pena mantenere.

Articoli correlati