Vi invitiamo a leggere la trascrizione della relazione di Nikolai Samokhvalov "Un approccio industriale alla messa a punto di PostgreSQL: esperimenti su database"
Shared_buffers = 25% – è tanto o poco? O è proprio il giusto? Come capire se questa raccomandazione – piuttosto obsoleta – si adatta al vostro caso specifico?
È giunto il momento di affrontare la questione della selezione dei parametri di postgresql.conf "in modo serio". Non tramite "autotuner" ciechi o raccomandazioni obsolete provenienti da articoli e blog, ma basandosi su:
- esperimenti rigorosamente calibrati su database, condotti in modo automatizzato, in grandi quantità e in condizioni il più possibile vicine a quelle "di produzione".
- una profonda comprensione delle peculiarità del funzionamento del DBMS e del sistema operativo.
Utilizzando Nancy CLI (), esamineremo un caso specifico – i famosi shared_buffers – in diverse situazioni, in diversi progetti e cercheremo di capire come ottimizzare la configurazione per la nostra infrastruttura, DB e carico di lavoro.

Si parlerà di esperimenti sui database. Questa è una storia che dura da poco più di sei mesi.

Un po' su di me. Ho oltre 14 anni di esperienza con Postgres. Ho fondato diverse aziende nel campo dei social network. In tutte queste ho utilizzato e utilizzo ancora Postgres.
Inoltre, il gruppo RuPostgres su Meetup è al secondo posto nel mondo. Stiamo avvicinandoci lentamente a 2000 membri. RuPostgres.org.
E in numerose conferenze, tra cui Highload, sono responsabile dei database, in particolare di Postgres, fin dalla sua fondazione.

Negli ultimi anni ho ripreso la mia pratica di consulenza su Postgres in 11 fusi orari da qui.

Quando l'ho fatto alcuni anni fa, avevo avuto una pausa dal lavoro attivo con Postgres, probabilmente dal 2010. Sono rimasto sorpreso da quanto poco siano cambiati i compiti quotidiani di un DBA e da quanto lavoro manuale rimanga ancora da fare. Ho subito pensato che ci fosse qualcosa che non andava, e che fosse necessario automatizzare di più.
E poiché tutto ciò avveniva a distanza, la maggior parte dei clienti si trovava nel cloud. E già molte cose erano chiaramente automatizzate. Di questo parlerò più avanti. In altre parole, tutto ciò ha portato all'idea che dovessero esserci una serie di strumenti, cioè una piattaforma in grado di automatizzare praticamente tutte le operazioni di un DBA, in modo da poter gestire un gran numero di database.

In questo rapporto non ci saranno:
- «Pallottole d'argento» e affermazioni del tipo – metti 8 GB o 25 % shared_buffers e andrà tutto bene. Di shared_buffers parleremo poco.
- Componenti «hardcore».

E cosa ci sarà?
- Ci saranno principi di ottimizzazione che applichiamo e sviluppiamo. Ci saranno varie idee che si presentano lungo il nostro cammino e diversi strumenti che creiamo principalmente in Open Source, cioè costruiamo la base in Open Source. Inoltre, gestiamo ticket e praticamente tutta la comunicazione in Open Source. Potete vedere cosa stiamo facendo ora, cosa ci sarà nel prossimo rilascio, ecc.
- Ci sarà anche una certa esperienza nell'uso di questi principi e strumenti in diverse aziende: da piccoli startup a grandi compagnie.

Come si sviluppa tutto questo?

Innanzitutto, l'obiettivo principale di un DBA, oltre a garantire la creazione di istanze, il deployment di backup, ecc., è identificare i colli di bottiglia e ottimizzare le prestazioni.

Attualmente è così che funziona. Guardiamo il monitoraggio, vediamo qualcosa, ma mancano alcuni dettagli. Iniziamo a scavare più a fondo, di solito manualmente, e comprendiamo come affrontare la situazione in un modo o nell'altro.

Ci sono due approcci. Pg_stat_statements è la soluzione standard predefinita per identificare le query lente. Analizzando i log di Postgres con pgBadger.
Entrambi gli approcci presentano seri svantaggi. Nel primo approccio, perdiamo tutti i parametri. Se vediamo gruppi SELECT * FROM table where la colonna è uguale al segno «?» o «$» a partire dalla versione 10 di Postgres, non sappiamo se si tratta di un index scan o un seq scan. Dipende molto dal parametro. Se inserisci un valore raro, si avrà un index scan. Se inserisci un valore che occupa il 90% della tabella, sarà chiaramente un seq scan, perché Postgres conosce le statistiche. Questo è un grande svantaggio di pg_stat_statements, anche se sono in corso dei miglioramenti.
L'aspetto principale dei log analizzati è che non puoi permetterti di impostare «log_min_duration_statement = 0», in genere. Di questo parleremo anche. Pertanto, non hai una visione completa. Una query molto veloce può consumare una grande quantità di risorse, ma non la vedrai, perché è al di sotto della tua soglia.
Come risolvono i DBA i problemi riscontrati?

Ad esempio, abbiamo riscontrato un problema. Cosa si fa di solito? Se sei uno sviluppatore, lavorerai su un'istanza di dimensioni diverse. Se sei un DBA, hai un ambiente di staging. E questo ambiente può essere solo uno. Può essere fermo da sei mesi. E pensi di passare alla produzione. Anche i DBA più esperti controllano successivamente in produzione, su una replica. A volte creano un indice temporaneo, verificano che funzioni, lo eliminano e lo restituiscono agli sviluppatori affinché lo inseriscano nei file di migrazione. Questo è il tipo di follia che accade ora. Ed è un problema.

- Ottimizzare le configurazioni.
- Ottimizzare il set di indici.
- Modificare la query SQL stessa (questo è il modo più complesso).
- Aggiungere risorse (il metodo più semplice nella maggior parte dei casi).

Ci sono molte cose da considerare. Ci sono molti parametri in Postgres. Bisogna sapere molte cose. Ci sono molti indici in Postgres, grazie anche agli organizzatori di questa conferenza. È importante conoscere tutto questo e proprio per questo i DBA non specializzati possono avere l'impressione che i DBA praticano una sorta di magia nera. Ci vogliono circa 10 anni di esperienza per iniziare a comprendere tutto in modo adeguato.
E io sono un combattente contro questa magia nera. Voglio fare in modo che ci sia tecnologia e non solo intuizione in tutto ciò.
Esempi dalla vita

Questo l'ho osservato in almeno due progetti, incluso il mio. Un altro post sul blog ci dice che un valore di 1.000 per default_statistict_target è positivo. Va bene, proviamo in produzione.

E qui noi, utilizzando il nostro strumento due anni dopo grazie agli esperimenti sulle basi di dati di cui parliamo oggi, possiamo confrontare ciò che era e ciò che è diventato.

E per questo dobbiamo creare un esperimento. Esso consiste di quattro parti.
- La prima è l'ambiente. Abbiamo bisogno dell'hardware. E quando arrivo in un'azienda e firmo un contratto, chiedo di avere una macchina uguale a quella in produzione. Ho bisogno di almeno un hardware uguale per ciascuno dei vostri Master. Può essere una macchina virtuale in Amazon o Google, oppure mi serve proprio quella macchina. Cioè, voglio ricreare l'ambiente. E nel concetto di ambiente includiamo la versione principale di Postgres.
- La seconda parte è l'oggetto delle nostre ricerche. È il database. Può essere creato in vari modi. Vi mostrerò come.
- La terza parte riguarda il carico. Questo è il momento più complesso.
- E la quarta parte riguarda ciò che verifichiamo, cioè con cosa confronteremo. Possiamo ad esempio modificare uno o più parametri nella configurazione, o possiamo creare un indice, e così via.

Avviamo l'esperimento. Ecco pg_stat_statements. A sinistra c'è quello che era, a destra c'è quello che è diventato.

A sinistra default_statistics_target = 100, a destra = 1 000. Vedo che ci ha aiutato. In generale, tutto è migliorato del 8%.

Ma se scorriamo verso il basso, vedremo i gruppi di query da pgBadger o da pg_stat_statements. Qui ci sono due opzioni. Vediamo che una certa query è diminuita dell'88%. E qui entra in gioco l'approccio ingegneristico. Possiamo scavare ulteriormente per capire perché è diminuita. Dobbiamo comprendere cosa è successo con le statistiche. Perché un maggior numero di bucket nelle statistiche porta a risultati peggiori.

Oppure possiamo non approfondire e fare "ALTER TABLE … ALTER COLUMN" riportando 100 bucket di nuovo nelle statistiche di questa colonna. E con un ulteriore esperimento possiamo confermare che questa soluzione ha funzionato. Questo è l'approccio ingegneristico che ci aiuta a vedere il quadro complessivo e a prendere decisioni basate sui dati, non sull'intuizione.


Alcuni esempi da altri settori. Nei test ci sono test CI da molti anni. E nessun progetto sensato vivrebbe senza test automatizzati.

In altri settori: nell'aviazione, nell'automobilismo, quando testiamo l'aerodinamica, abbiamo anche la possibilità di eseguire esperimenti. Non lanceremo qualcosa nello spazio direttamente dai disegni né metteremo subito un'auto in strada. Ad esempio, abbiamo una galleria del vento.
Dall'osservazione di altri settori possiamo trarre delle conclusioni.

Innanzitutto, disponiamo di un ambiente speciale. È simile alla produzione, ma non proprio. La sua principale caratteristica è che deve essere economico, ripetibile e massimamente automatizzato. Inoltre, devono esserci strumenti speciali per eseguire analisi dettagliate.
Probabilmente, quando lanciamo l'aereo e voliamo, abbiamo meno opportunità di esaminare ogni millimetro della superficie dell'ala rispetto a quanto potremmo fare in una galleria del vento. Abbiamo più strumenti per la diagnostica. Possiamo permetterci di aggiungere più pesante, cosa che non possiamo fare con un aereo in volo. Lo stesso vale per Postgres. In alcuni casi, possiamo abilitare il logging completo delle query durante gli esperimenti. E non vogliamo farlo in producción. Potremmo anche includerlo nei piani tramite auto_explain.
E come ho già detto, un alto livello di automazione significa che premiamo un pulsante e ripetiamo. Deve essere così, per poter fare molti esperimenti, per farlo diventare un flusso.
Nancy CLI – la base del "laboratorio DB"

Ecco, abbiamo creato qualcosa del genere. Cioè, ho parlato di queste idee a giugno, quasi un anno fa. E abbiamo già nel Open Source quella che chiamiamo Nancy CLI. È la base per costruire un laboratorio di database.

— È in Open Source, su Gitlab. Potete dirlo, potete provarlo. Ho fornito un link nelle diapositive. Potete cliccare e troverete per tutti i parametri.
Certo, c'è ancora molto in fase di sviluppo. Ci sono molte idee. Ma questo è già ciò che applichiamo praticamente ogni giorno. E quando ci viene un'idea – per esempio, se eliminiamo 40 000 000 righe e tutto si blocca in IO, possiamo fare un esperimento e osservare meglio per capire cosa sta succedendo e poi cercare di risolverlo al volo. Cioè, facciamo un esperimento. Ad esempio, cambiamo qualcosa e vediamo cosa succede. E non lo facciamo in produzione. Questa è l'essenza dell'idea.

Dove può funzionare? Può funzionare localmente, cioè si può fare ovunque, si può anche avviare su un MacBook. Serve Docker, via. E basta. Può essere eseguito su qualche istanza su hardware, oppure in una macchina virtuale, ovunque.
C'è anche la possibilità di avviare remote su Amazon EC2 Instance, negli spot. Questa è un'opzione molto interessante. Ad esempio, ieri abbiamo condotto più di 500 esperimenti su un'istanza i3, partendo dalla più piccola fino ad arrivare all'i3-16-xlarge. E 500 esperimenti ci sono costati 64 dollari. Ognuno durava 15 minuti. Grazie all'uso degli spot, è molto economico – uno sconto del 70%, con la tariffazione al secondo di Amazon. Puoi fare davvero molto. Puoi condurre una ricerca reale.

Sono supportate tre versioni principali di Postgres. Non è così difficile adattare alcune versioni vecchie e la nuova versione 12 anch'essa.

Possiamo definire l'oggetto in tre modi. Questi sono:
- Dump/file sql.
- Il metodo principale è clonare la directory PGDATA. Di solito viene prelevato dal server di backup. Se hai backup binari normali, puoi creare cloni da lì. Se hai servizi cloud, la società del cloud, come Amazon e Google, lo farà per te. Questo è il modo principale per i cloni di un vero ambiente di produzione. Procediamo in questo modo per il deployment.
- L'ultimo metodo è utile per le ricerche, quando si desidera capire come funziona qualcosa in Postgres. Questo è pgbench. Puoi generare utilizzando pgbench. È semplicemente un'opzione «db-pgbench». Gli dici quale scala utilizzare. E tutto verrà generato nel cloud, come indicato.

E il carico:
- Possiamo eseguire il carico in un singolo thread SQL. Questo è il modo più primitivo.
- Oppure possiamo emulare il carico. E possiamo emularlo in primo luogo nel seguente modo. Dobbiamo raccogliere tutti i log. Ed è un processo doloroso. Ti mostrerò perché. E utilizziamo pgreplay, che è integrato in Nancy.
- Un'altra opzione è il cosiddetto carico artigianale, per il quale mettiamo in campo un certo impegno. Analizzando il carico attuale sul sistema di produzione, estraiamo i gruppi di query più importanti. E con pgbench possiamo emulare questo carico in laboratorio.

- Oppure dobbiamo eseguire qualche SQL, cioè controlliamo una migrazione, creiamo un indice, eseguiamo ANALYZE. E vediamo cosa c'era prima e dopo il vacuum. In generale, qualsiasi SQL.
- Possiamo modificare uno o più parametri nella configurazione. Possiamo chiedere di controllare, ad esempio, 100 valori su Amazon per il nostro database da un terabyte. E dopo alcune ore avrete il risultato. In genere, il database da un terabyte richiede alcune ore per essere distribuito. Ma nella fase di sviluppo c'è una patch, quindi abbiamo la possibilità di eseguire una serie di test, cioè potete usare lo stesso pgdata sullo stesso server e continuare a verificare. Postgres verrà riavviato e le cache verranno azzerate. E potete eseguire il carico.

- Arriva una directory con un sacco di file, a partire dagli snapshot pgstat***. E qui le cose interessanti sono pg_stat_statements, pg_stat_kcache. Questi sono due estensioni che analizzano le query. E pg_stat_bgwriter contiene non solo le statistiche di pgwriter, ma anche informazioni sui checkpoint e su come i backend gestiscono i buffer sporchi. È interessante da vedere. Ad esempio, quando configurate shared_buffers, è molto interessante osservare quanto è stato rimosso.
- Arrivano anche i log di Postgres. Due log: il log di preparazione e il log di riproduzione del carico.
- Una funzionalità relativamente nuova sono i FlameGraphs.
- Inoltre, se hai utilizzato pgreplay o pgbench per simulare il carico, avranno una restituzione nativa. Potrai vedere la latenza e il TPS. Sarà possibile capire come si sono comportati.
- Informazioni sul sistema.
- Controlli di base per CPU e IO. Questo è particolarmente utile per un'istanza EC2 su Amazon, quando vuoi avviare 100 istanze identiche in parallelo e testarne 100 diverse, avrai quindi 10.000 esperimenti. Devi assicurarti di non ottenere un'istanza difettosa, già sovraccaricata da qualcun altro. Su questa macchina potrebbero esserci altre attività e ti rimarrebbero poche risorse. Risultati come questi è meglio escluderli. Proprio con l'aiuto di sysbench di Alexey Kopytov facciamo alcuni brevi controlli, che permetteranno di confrontare con altri, quindi capirai come si comporta la CPU e come si comporta l'IO.

Quali sono le complessità tecniche considerando diversi esempi aziendali?

Supponiamo di voler riprodurre un carico reale utilizzando i log. È un'ottima idea, se è scritto in Open Source, utilizziamo pgreplay. Ma per farlo funzionare correttamente, devi abilitare la registrazione completa delle query con parametri e tempistiche.
Ci sono alcune difficoltà riguardo a duration e timestamp. Possiamo tralasciare tutto questo. La domanda principale è: potete permettervi di fare questo o no?

Il problema è che potrebbe non essere disponibile. Prima di tutto, dovete capire quale flusso verrà scritto nel log. Se avete pg_stat_statements, potete utilizzare questa query (il collegamento sarà disponibile nelle diapositive) per capire quanti byte verranno scritti al secondo.
Guardiamo la lunghezza della query. Ciò che trascuriamo è il fatto che non ci sono parametri, ma conosciamo la lunghezza della query e sappiamo quante volte al secondo viene eseguita. In questo modo possiamo stimare quanti byte vengono scritti al secondo. Potremmo sbagliare di due volte, ma la direzione la capiremo sicuramente in questo modo.
Possiamo vedere che questa query viene eseguita 802 volte al secondo. E vediamo che bytes_per sec sarà di circa 300 kB/s. E, di norma, possiamo permetterci un tale flusso.

Ma! Il fatto è che ci sono diversi sistemi di logging. E per impostazione predefinita, di solito, le persone usano 'syslog'.

E se avete syslog, potreste avere un'immagine del genere. Prenderemo pgbench, attiveremo il logging delle query e vedremo cosa succede.

Senza logging – questo è il grafico a sinistra. Abbiamo ottenuto 161.000 TPS. Con syslog – su Ubuntu 16.04 su Amazon otteniamo 37.000 TPS. Se cambiamo a due altri metodi di logging, la situazione migliora notevolmente. Cioè, ci aspettavamo una riduzione, ma non così drastica.

E su CentOS 7, dove è coinvolto anche journald, che trasforma i log in formato binario per una ricerca più facile, la situazione è davvero pessima, con una riduzione di 44 volte nei TPS.

E questo è ciò con cui convivono le persone. Spesso nelle aziende, specialmente quelle grandi, è molto difficile cambiarlo. Se potete abbandonare syslog, vi preghiamo di farlo.

- Valutate gli IOPS e il throughput di scrittura.
- Controllate il vostro sistema di logging.
- Se il carico previsto è eccessivo, prendere in considerazione il campionamento.

Abbiamo pg_stat_statements. Come ho detto, deve essere presente. Possiamo prendere e descrivere ogni gruppo di query in un file specifico. E poi possiamo utilizzare una funzione molto comoda in pgbench – la possibilità di fornire diversi file utilizzando l'opzione "-f."
Lui comprende molti "-f". E possiamo specificare con "@" alla fine quale percentuale ogni file dovrebbe avere. Possiamo dire, ad esempio, che questo deve essere eseguito nel 10% dei casi e quest'altro nel 20%. Questo ci avvicinerà a ciò che vediamo in produzione.

E come possiamo capire cosa abbiamo in produzione? Qual è la percentuale e cosa significa? Qui ci allontaniamo un po'. Abbiamo un altro prodotto . Anche questo è un database Open Source. E attualmente lo stiamo sviluppando attivamente.
È nato per motivi un po' diversi. Per la mancanza di monitoraggio. Cioè, arrivate, guardate il database, osservate i problemi che ci sono. E, di norma, fate un health_check. Se siete un DBA esperto, farete un health_check. Controllate l'uso degli indici, ecc. Se avete OKmeter, è fantastico. È un ottimo monitoraggio per Postgres. OKmeter.io – per favore, installatelo, è tutto realizzato molto bene. È a pagamento.
Se non lo avete, di norma, avrete poco. In monitoraggio di solito ci sono CPU, IO e con delle riserve, e basta. E noi abbiamo bisogno di di più. Abbiamo bisogno di vedere come funziona l'autovacuum, come funziona il checkpoint, nell'IO dobbiamo separare il checkpoint dal bgwriter e dai backend, ecc.
Il problema è che quando aiuti un'azienda di grandi dimensioni, non possono implementare rapidamente qualcosa. Non possono acquistare rapidamente OKmeter. Potrebbero farlo tra sei mesi. Non possono installare rapidamente alcuni pacchetti.
E ci è venuta l'idea di creare uno strumento speciale che non richiede alcuna installazione, cioè non devi installare nulla nel tuo ambiente di produzione. Lo installi sul tuo laptop o su un server di osservazione da cui lo esegui. Analizzerà molte cose: il sistema operativo, il file system e PostgreSQL stesso, facendo alcune query leggere che puoi eseguire direttamente in produzione senza problemi.
Lo abbiamo chiamato Postgres-checkup. In termini medici, è un controllo regolare della salute. Se parliamo di automobili, è come il tagliando. Effettui il tagliando della tua auto ogni sei mesi o un anno, a seconda della marca. E tu fai il tagliando per il tuo database? Cioè, fai ricerche approfondite regolarmente? È qualcosa che va fatto. Se esegui backup, fai anche il checkup, è altrettanto importante.
E abbiamo uno strumento di questo tipo. Ha iniziato a svilupparsi attivamente solo circa tre mesi fa. È ancora giovane, ma ha già molte funzionalità.

Raccogliamo i gruppi di query più "influenti" – rapporto K003 in Postgres-checkup
E ci sono gruppi di rapporti K. Attualmente ci sono tre rapporti. E c'è questo rapporto K003. Qui troviamo l'apice di pg_stat_statements, ordinato per total_time.
Quando ordiniamo i gruppi di query per total_time, vediamo in cima un gruppo che carica maggiormente il nostro sistema, cioè consuma una quantità maggiore di risorse. Perché li chiamo gruppi di query? Perché abbiamo escluso i parametri. Non sono più query, ma gruppi di query, sono astratti.
E se ottimizziamo dall'alto verso il basso, possiamo alleggerire le nostre risorse e rimandare il momento in cui dovremo fare un upgrade. È un ottimo modo per risparmiare denaro.
Forse non è il modo migliore per prendersi cura degli utenti, perché potremmo non vedere casi rari ma molto frustranti, quando una persona ha atteso 15 secondi. In totale sono così rari che non li notiamo, ma stiamo gestendo le risorse.

Cosa è successo in questa tabella? Abbiamo fatto due istantanee. Postgres_checkup ti fornirà la delta per ogni metrica: per total-time, calls, rows, shared_blks_read, ecc. Tutto, abbiamo calcolato la delta. Un grande problema con pg_stat_statements è che non ricorda quando è stato effettuato il reset. Se pg_stat_database ricorda, pg_stat_statements non lo fa. Vedi quel numero di 1.000.000, ma da dove lo abbiamo ottenuto, non lo sappiamo.

Qui invece lo sappiamo, abbiamo due istantanee. Sappiamo che la delta in questo caso era di 56 secondi. Un intervallo molto breve. Abbiamo ordinato per total_time. E poi possiamo differenziare, cioè dividiamo tutte le metriche per la durata. Se dividiamo ogni metrica per la durata, avremo il numero di chiamate al secondo.
Poi, total_time per secondo è la mia metrica preferita. Si misura in secondi, cioè quanti secondi la nostra sistema ha impiegato per eseguire questo gruppo di query al secondo. Se vedi più di un secondo al secondo, significa che hai bisogno di più di un core. È una metrica molto utile. Puoi capire, per esempio, che a quel tizio servono almeno tre core.
Questo è il nostro fiore all'occhiello, non ho mai visto nulla di simile. Notate - è qualcosa di molto semplice - secondo dopo secondo. A volte, quando la CPU è al 100%, il tempo di risposta è di mezz'ora per secondo, ossia spendi mezz'ora solo per questa richiesta.
Poi vediamo le righe al secondo. Sappiamo quante righe sono state restituite al secondo.
E c'è anche un'altra cosa interessante. Quante volte abbiamo letto shared_buffers al secondo dal shared_buffers stesso. I colpi erano già lì, e le righe le abbiamo prese dalla cache del sistema operativo o dal disco. La prima opzione è veloce, la seconda può essere veloce, ma dipende dalla situazione.
Il secondo modo di differenziare è dividere il numero di richieste in questo gruppo. Nella seconda colonna avrete sempre una richiesta divisa per richiesta. E poi è interessante sapere quanti millisecondi ci sono stati in questa richiesta. Sappiamo come si comporta mediamente questa richiesta. Ci abbiamo messo 101 millisecondi per ogni richiesta. Questa è una metrica tradizionale di cui abbiamo bisogno per comprendere.
Quante righe ha restituito mediamente ogni richiesta. Vediamo che il gruppo restituiva 8. Quante in media sono state ottenute e lette dalla cache. Notiamo che tutto è stato memorizzato in modo efficiente. Solo hit per il primo gruppo.
E la quarta sottoriga in ogni riga rappresenta la percentuale rispetto al numero totale. Abbiamo delle chiamate. Supponiamo di avere 1.000.000. Possiamo capire quale contributo dà questo gruppo. Vediamo che, in questo caso, il primo gruppo contribuisce con meno dello 0,01%. Cioè, è così lento che non appare nel quadro generale. Il secondo gruppo, invece, rappresenta il 5% delle chiamate. Cioè, il 5% di tutte le chiamate proviene dal secondo gruppo.
Anche per il total_time è interessante. Sui primi gruppi di richieste abbiamo speso il 14% del tempo totale di esecuzione. Sul secondo gruppo abbiamo speso l'11%, e così via.
Non entrerò nei dettagli, ma ci sono delle sottigliezze. Riportiamo un errore in alto, perché quando confrontiamo, gli snapshot possono variare, cioè alcune richieste possono mancare e non essere presenti nel secondo, mentre altre possono apparire nuove. E lì calcoliamo l'errore. Se vedi 0, è un segnale positivo. Significa che non ci sono errori. Se il tasso di errore è fino al 20%, va bene.

Ora torniamo al nostro argomento. Dobbiamo catalogare il workload. Procediamo dall'alto verso il basso, finché non raggiungiamo l'80% o il 90%. Di solito si tratta di 10-20 gruppi. Creiamo i file per pgbench, utilizzando valori casuali. A volte, purtroppo, non è possibile. Con Postgres 12 avremo più possibilità di applicare questo approccio.
E in questo modo accumuliamo l'80-90% del total_time. Cosa dobbiamo inserire dopo il «@»? Guardiamo le chiamate, osserviamo quanti percentuali e comprendiamo quanto dovremmo avere qui. Da queste percentuali possiamo capire come bilanciare ciascun file. Dopo di che utilizziamo pgbench e iniziamo a lavorare.

Abbiamo anche K001 e K002.
K001 è una grande stringa con quattro sotto-stringhe. Questa è la caratteristica del nostro carico complessivo. Osservate la seconda colonna e la seconda sotto-stringa. Vediamo che è circa 1,5 secondi al secondo, quindi se abbiamo due core, andrà bene. Sarà circa il 75% di utilizzo. E così funzionerà. Se abbiamo 10 core, saremo completamente a posto. Così possiamo valutare le risorse.
K002 è ciò che chiamo classi di query, ossia SELECT, INSERT, UPDATE, DELETE. E separatamente SELECT FOR UPDATE, perché blocca.
E qui possiamo concludere che le query SELECT normali rappresentano l'82% di tutte le chiamate, ma il 74% del total_time. Cioè, vengono chiamate molte volte, ma consumano meno risorse.

E torniamo alla domanda: «Come possiamo configurare correttamente shared_buffers?». Osservo che la maggior parte dei benchmark si basa sull'idea di verificare qual è il throughput, ossia quale sarà la capacità di elaborazione. Questa viene solitamente misurata in TPS o QPS.
E cerchiamo di ottenere il massimo dalla macchina con i parametri di tuning per raggiungere il maggior numero possibile di transazioni al secondo. Qui abbiamo 311 selezioni al secondo.

Ma nessuno guida verso il lavoro e torna a casa a piena velocità. È sciocco. Lo stesso vale per i database. Non dobbiamo viaggiare a piena velocità, e nessuno lo fa. Nessuno vive in un ambiente di produzione con il 100% della CPU. Anche se, forse, qualcuno lo fa, ma non è una buona cosa.
L'idea è che normalmente operiamo al 20% delle nostre capacità, idealmente non oltre il 50%. Ci sforziamo di ottimizzare i tempi di risposta per i nostri utenti prima di tutto. Dobbiamo gestire le nostre operazioni in modo da garantire la minima latenza a una velocità del 20%, per così dire. Questa è un'idea che cerchiamo di sfruttare anche nei nostri esperimenti.

E in conclusione, i consigli:
- Assicurati di creare un Database Lab.
- Se possibile, rendilo on demand, in modo che possa essere attivato temporaneamente – gioca e poi elimina. Se hai risorse cloud, questo è implicito, cioè assicurati di avere molte risorse disponibili.
- Sii curioso. E se qualcosa non funziona, verifica con esperimenti come si comporta. Puoi usare Nancy per formarti e vedere come funziona il database.
- Punta a tempi di risposta minimi.
- E non temere il codice sorgente di Postgres. Quando lavori con il codice sorgente, devi conoscere l'inglese. Ci sono molti commenti, tutto è spiegato.
- E controlla regolarmente la salute del database, almeno una volta ogni tre mesi, manualmente o usando Postgres-checkup.

Domande
Grazie mille! È stata un'idea molto interessante.
Due elementi.
Sì, due pezzi. Solo che non ho capito bene. Quando lavoriamo con Nancy, possiamo regolare solo un parametro o un intero gruppo?
Abbiamo il parametro di configurazione delta. Puoi modificarne quanti ne vuoi subito. Ma bisogna capire che quando cambi molte cose, potresti fare conclusioni sbagliate.
Sì. Perché ho chiesto? Perché è difficile condurre esperimenti quando hai solo un parametro. Lo modifichi, vedi come funziona. Lo imposti. Poi cominci con il successivo.
Puoi regolare più cose contemporaneamente, ma dipende dalla situazione, ovviamente. Ma è meglio testare un'idea alla volta. Ieri ci è venuta un'idea. Avevamo una situazione molto simile. C'erano due configurazioni. E non riuscivamo a capire perché ci fosse una grande differenza. E ci è venuta l'idea che bisogna usare la diacronia per capire e trovare in cosa consistesse la differenza. Puoi subito rendere metà dei parametri uguali, poi un quarto, e così via. Tutto è flessibile.
E c'è un'altra domanda. Il progetto è giovane e in fase di sviluppo. La documentazione è già pronta, c'è una descrizione dettagliata?
Ho creato un link specifico per la descrizione delle caratteristiche. È disponibile. Ma ci sono ancora molte cose mancanti. Sto cercando persone che condividano le mie idee. E le trovo quando parlo. È davvero fantastico. Qualcuno già lavora con me, qualcun altro ha aiutato e ha fatto qualcosa. E se questo argomento ti interessa, fammi sapere – cosa manca.
Quando avremo pronto il laboratorio, potrebbe esserci un feedback. Vedremo. Grazie!
Buongiorno! Grazie per l'intervento! Ho notato che c'è supporto per Amazon. È prevista anche la supporto per GSP?
Ottima domanda. Abbiamo iniziato e al momento abbiamo sospeso il progetto perché vogliamo risparmiare. C'è supporto per l'esecuzione in localhost. Puoi creare un'istanza da solo e lavorare localmente. A proposito, così facciamo noi. In Getlab faccio così, lì su GSP. Ma non vediamo al momento il senso di fare un orchestrazione di questo tipo, perché non ci sono spazi economici da parte di Google. Ci sono istanze ???, ma hanno delle restrizioni. Primo, hanno sempre solo uno sconto del 70% e non puoi modificare il prezzo. Negli spazi aumentiamo il prezzo del 5-10% per ridurre la probabilità che ti elimina. In altre parole, risparmi con gli spazi, ma possono essere ritirati in qualsiasi momento. Se imposti un prezzo leggermente superiore a quello degli altri, verrai eliminato più tardi. Google ha una specifica completamente diversa. E c'è anche una restrizione molto negativa: vivono solo per 24 ore. A volte vogliamo condurre esperimenti per 5 giorni. Ma questo è possibile negli spazi, a volte gli spazi vivono per mesi.
Salve! Grazie per la presentazione! Hai menzionato il checkup. Come calcoli gli errori stat_statements?
Ottima domanda. Posso spiegare e raccontare in dettaglio. In breve, osserviamo come è cambiato il set di gruppi di query: quanti sono scomparsi e quanti sono nuovi. E poi esaminiamo due metriche: total_time e calls, quindi ci sono due errori. E vediamo quale contributo hanno i gruppi che sono cambiati. Ci sono due sottogruppi: quelli che se ne sono andati e quelli che sono arrivati. Analizziamo il loro contributo all'immagine complessiva.
Non temete che possa girare due o tre volte durante il tempo tra i snapshot?
Cioè, si sono registrati di nuovo o come?
Ad esempio, questa query è già stata espulsa una volta, poi è tornata ed è stata espulsa di nuovo, poi è tornata ancora ed è stata espulsa. E qui hai fatto qualche calcolo e dov'è tutto questo?
Bella domanda, bisogna esaminare.
Ho fatto qualcosa di simile. Certo, l'ho fatto in modo più semplice, l'ho fatto da solo. Ma ho dovuto resettare, fare un reset stat_statements e orientarmi nel momento dello snapshot, dove c'era meno di una certa quota, che non aveva comunque raggiunto il limite, quanto stat_statements può accumulare. E mi orienterei sul fatto che, molto probabilmente, nulla è stato espulso.
Sì, sì.
Ma non capisco come possiamo farlo in modo affidabile.
Purtroppo non ricordo esattamente se utilizziamo il testo della query o il queryid con pg_stat_statements per orientarci. Se ci riferiamo al queryid, allora in teoria stiamo confrontando cose comparabili.
No, può essere sovrascritto più volte tra gli snapshot e tornare di nuovo.
Con lo stesso id?
Sì.
Studieremo questa questione. È una buona domanda. Dobbiamo approfondire. Ma per ora, ciò che vediamo è che abbiamo scritto 0...
È sicuramente un caso raro, ma sono rimasto colpito quando ho scoperto che stat_statements può essere sovrascritto.
In Pg_stat_statements può esserci di tutto. Abbiamo riscontrato che se track_utility è attivo, anche i set vengono tracciati.
Sì, certo.
E se hai java hibernate, che è casuale, inizia a bloccarsi la tabella hash. E non appena disattivi un'applicazione molto carica, hai 50-100 gruppi. E lì tutto è più o meno stabile. Uno dei modi per affrontare questo problema è aumentare pg_stat_statements.max.
Sì, ma bisogna sapere quanto. E bisogna tenerne traccia. Io lo faccio. Cioè, ho pg_stat_statements.max. E controllo che nel momento dello snapshot non ho raggiunto il 70%. Bene, significa che non abbiamo perso nulla. Facciamo un reset. E accumuliamo di nuovo. Se nel prossimo snapshot siamo sotto il 70%, significa che probabilmente non abbiamo perso nulla nuovamente.
Sì. Di default ora sono 5.000. E a molti basta questo.
Di solito sì.
Video:

P.S. Aggiungo che se in Postgres ci sono dati riservati che non devono finire nell'ambiente di test, si può utilizzare . Lo schema è all'incirca il seguente:

Fonte: habr.com
