Ti propongo di dare un'occhiata alla trascrizione della relazione di Nikolai Samokhvalov "Approccio industriale al tuning di PostgreSQL: esperimenti su database"
Shared_buffers = 25% – è troppo o troppo poco? O va bene così? Come capire se questa – piuttosto obsoleta – raccomandazione è adatta al tuo caso specifico?
È giunto il momento di affrontare la questione della selezione dei parametri di postgresql.conf "come si deve". Non con l'ausilio di "autotuner" ciechi o consigli obsoleti da articoli e blog, ma sulla base di:
- esperimenti rigorosamente calcolati su DB, effettuati in modo automatizzato, in grande quantità e in condizioni il più possibile vicine a quelle "di produzione",
- una comprensione profonda delle peculiarità del funzionamento del DBMS e del sistema operativo.
Utilizzando Nancy CLI (), esamineremo un caso concreto – i famigerati shared_buffers – in diverse situazioni, in diversi progetti e cercheremo di capire come ottimizzare le impostazioni 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 un'esperienza con Postgres di oltre 14 anni. Ho fondato diverse aziende nel settore dei social network. In ognuna di esse sono stati utilizzati Postgres e sono ancora utilizzati.
Inoltre, il gruppo RuPostgres su Meetup è al secondo posto a livello mondiale. Ci stiamo avvicinando lentamente ai 2000 membri. RuPostgres.org.
E nelle varie conferenze, inclusa Highload, mi occupo dei database, in particolare di Postgres sin dalla sua fondazione.

E negli ultimi anni ho rilanciato la mia attività di consulenza su Postgres in 11 fusi orari di distanza.

Quando l'ho fatto qualche anno fa, avevo preso una pausa dal lavoro pratico con Postgres, probabilmente dal 2010. Sono rimasto sorpreso da quanto poco siano cambiati i compiti quotidiani dei DBA, da quanto sia comunque necessario fare ancora molto lavoro manuale. Ho subito pensato che ci fosse qualcosa che non andava, dovevo automatizzare di più.
E dato che tutto ciò avveniva a distanza, la maggior parte dei clienti era nel cloud. E già molte attività sono state automatizzate, è ovvio. Ne parlerò più tardi. Cioè, tutto ciò ha portato all'idea che dovrebbero esserci diversi strumenti, cioè una sorta di piattaforma, che automatizzerà praticamente tutte le azioni del DBA, in modo da poter gestire un gran numero di database.

In questa relazione non ci saranno:
- «Pallottole d'argento» e affermazioni del tipo – imposta 8 GB o 25 % di shared_buffers e andrà tutto bene. Si parlerà di shared_buffers non così tanto.
- Componenti hardcore.

E cosa succederà?
- Ci saranno principi di ottimizzazione che applichiamo e sviluppiamo. Ci saranno varie idee che ci vengono in mente lungo il cammino e diversi strumenti che creiamo per lo più in Open Source, cioè la base la facciamo in Open Source. Inoltre, abbiamo ticket, tutta la comunicazione praticamente in Open Source. Potete vedere cosa stiamo facendo ora, cosa ci sarà nella prossima release, ecc.
- Ci sarà anche una certa esperienza nell'utilizzo di questi principi e strumenti in diverse aziende: da piccoli startup a grandi imprese.

Come si sviluppa tutto questo?

In primo luogo, il compito principale del DBA, oltre a garantire la creazione di istanze, il dispiegamento dei backup, ecc., è la ricerca dei colli di bottiglia e l'ottimizzazione delle prestazioni.

Ora funziona in questo modo. Guardiamo il monitoraggio, vediamo qualcosa, ci mancano alcuni dettagli. Iniziamo a scavare più a fondo, di solito manualmente, e capiamo come affrontare la situazione.

Ci sono due approcci. Pg_stat_statements è la soluzione standard per individuare le query lente. E l'analisi dei log di Postgres utilizzando pgBadger.
Ciascuno degli approcci ha seri svantaggi. Nel primo approccio abbiamo buttiamo via tutti i parametri. E se vediamo gruppi SELECT * FROM table where una colonna è uguale al segno «?» o «$» a partire dalla versione Postgres 10. Non sappiamo se si tratta di un index scan o di un seq scan. Dipende molto dal parametro. Se ci metti un valore raro, sarà index scan. Se metti un valore che rappresenta il 90 % della tabella, sarà ovviamente seq scan, perché Postgres conosce la statistica. E questo è un grande svantaggio di pg_stat_statements, anche se si stanno facendo dei lavori.
L'analisi dei log ha il principale svantaggio che non puoi permetterti di avere «log_min_duration_statement = 0», in genere. E di questo parleremo anche. Di conseguenza, non vedi l'intera situazione. E una query che è molto veloce può consumare una grande quantità di risorse, ma non la vedrai, perché è sotto la tua soglia.
Come risolvono i DBA i problemi trovati?

Ad esempio, abbiamo riscontrato un problema. Cosa si fa di solito? Se sei uno sviluppatore, lavorerai su qualche istanza che non è di quelle dimensioni. Se sei un DBA, hai uno staging. E può essercene solo uno. E questo è rimasto indietro di sei mesi. E pensi che andrà in produzione. E anche i DBA esperti controllano poi in produzione, su una replica. A volte creano un indice temporaneo, si assicurano che sia utile, lo eliminano e lo restituiscono agli sviluppatori per inselinarlo nei file di migrazione. Questo sta succedendo ora. Ed è un problema.

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

Ci sono molte cose da considerare. Ci sono molte leve in Postgres. È necessario sapere molto. Ci sono molti indici in Postgres, grazie anche agli organizzatori di questa conferenza. E bisogna sapere tutto questo, ed è proprio questo che dà ai non DBA l'impressione che i DBA si occupino di magia nera. Cioè, bisogna dedicarsi a questo per almeno 10 anni per iniziare a capire tutto correttamente.
E io sono un combattente contro questa magia nera. Voglio fare in modo che ci sia tecnologia, e non intuito in tutto questo.
Esempi dalla vita

L'ho osservato in almeno due progetti, incluso il mio. Un ulteriore post sul blog ci informa che il valore di 1000 per default_statistic_target è buono. Va bene, proviamo in produzione.

E qui noi, usando il nostro strumento due anni dopo grazie a esperimenti su database di cui parliamo oggi, possiamo confrontare cosa c'era e cosa è diventato.

E per questo dobbiamo creare un esperimento. Esso è composto da quattro parti.
- La prima parte è l'ambiente. Abbiamo bisogno di hardware. E quando arrivo in un'azienda e firmo un contratto, chiedo che mi diano hardware identico a quello di produzione. Per ciascuno dei vostri Master ho bisogno di almeno un hardware identico. O è un'istanza virtuale su Amazon o Google, o ho bisogno di hardware proprio così. 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 diversi modi. Vi mostrerò come.
- La terza parte è il carico. Questo è il momento più complesso.
- E la quarta parte è ciò che controlliamo, cioè con cosa confronteremo. Supponiamo che possiamo cambiare uno o più parametri nella configurazione, oppure possiamo creare un indice, e così via.

Stiamo lanciando un esperimento. Ecco pg_stat_statements. A sinistra c'è quello che era. A destra c'è come è diventato.

A sinistra default_statistics_target = 100, a destra = 1 000. Vediamo che questo ci ha aiutato. In generale, tutto è migliorato dell'8%.

Ma se scorriamo verso il basso, ci saranno gruppi di query da pgBadger o da pg_stat_statements. Ci sono due opzioni. Vedremo che una certa query è diminuita dell'88%. E qui entra in gioco l'approccio ingegneristico. Possiamo approfondire ulteriormente, perché è interessante capire perché è diminuita. Dobbiamo capire cosa c'era con le statistiche. Perché più bucket nella statistica portano a risultati peggiori.

Oppure possiamo non approfondire, ma fare un 'ALTER TABLE … ALTER COLUMN' e riportarli a 100 bucket nella statistica di questa colonna. E poi, con un ulteriore esperimento, possiamo assicurarci che questa patch abbia funzionato. Tutto qui. Questo è l'approccio ingegneristico che ci aiuta a vedere il quadro e prendere decisioni basate sui dati, non sull'intuizione.


Alcuni esempi da altri settori. Nei test ci sono test CI già da molti anni. E nessun progetto sensato ormai può vivere senza test automatici.

In altri settori: nell'aviazione, nell'industria automobilistica, quando testiamo l'aerodinamica, abbiamo anche la possibilità di fare esperimenti. Non lanceremo qualcosa direttamente nello spazio dal progetto né porteremo un'auto sulla pista subito. Ad esempio, c'è una galleria del vento.
Dalle osservazioni di altri settori possiamo trarre conclusioni.

Per prima cosa, abbiamo un ambiente speciale. È vicino alla produzione, ma non troppo. La sua principale caratteristica è che deve essere economico, ripetibile e il più automatizzato possibile. E devono esserci strumenti specializzati per condurre un'analisi dettagliata.
È probabile che quando lanciamo l'aereo e siamo in volo, abbiamo meno opportunità di studiare ogni millimetro della superficie dell'ala rispetto a quanto possiamo fare in una galleria del vento. Abbiamo più strumenti per la diagnosi. Possiamo permetterci di caricare più cose pesanti, che non possiamo permetterci di installare sull'aereo in volo. Anche con Postgres. In alcuni casi possiamo attivare la registrazione completa delle query durante gli esperimenti. E noi non vogliamo farlo in produzione. Potremmo anche attivarlo in futuro con l'aiuto di auto_explain.
E come ho già detto, un alto livello di automazione significa che abbiamo premuto un pulsante e ripetuto. Così deve essere, per avere tanti esperimenti e per essere in modo continuativo.
Nancy CLI – la base del "laboratorio DB"

Ecco, abbiamo fatto una cosa del genere. Cioè, ho parlato di queste idee a giugno, quasi un anno fa. E abbiamo già in Open Source quella che chiamiamo Nancy CLI. Questa è la base per costruire un laboratorio per basi di dati.

– È in Open Source, su Gitlab. Potete dirlo, potete provarlo. Ho messo un link nelle slide. Potete cliccarlo e lì ci sarà per tutti i parametri.
Certo, c'è ancora molto in fase di sviluppo. Ci sono molte idee. Ma è già quello che applichiamo praticamente ogni giorno. E quando abbiamo un'idea – ad esempio, cosa succede se cancelliamo 40.000.000 righe e ci troviamo tutto bloccato su IO, possiamo fare un esperimento e guardare più da vicino per capire cosa sta succedendo e poi cercare di correggerlo al volo. Cioè, facciamo un esperimento. Ad esempio, regoliamo qualcosa e vediamo cosa otteniamo alla fine. 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, andiamo. E basta. Può essere avviato in qualche istanza su un server fisico, o in una macchina virtuale, ovunque.
C'è anche la possibilità di avviare remotamente su Amazon nei EC2 Instance, negli spot. E questa è un'ottima opportunità. Ad esempio, ieri abbiamo condotto più di 500 esperimenti su un'istanza i3, iniziando dalla più piccola fino a i3-16-xlarge. E questi 500 esperimenti ci sono costati 64 dollari. Ognuno è durato 15 minuti. Vale a dire, grazie all'utilizzo degli spot, è molto economico - uno sconto del 70%, tariffe al secondo di Amazon. Puoi fare davvero molto. Puoi condurre una ricerca reale.

E tre versioni principali di Postgres sono supportate. Non è così difficile adattare alcune versioni vecchie e la nuova versione 12.

Possiamo definire l'oggetto in tre modi. Questi sono:
- Dump/sql-file.
- Il modo principale è clonare la directory PGDATA. Di solito viene presa dal server di backup. Se hai backup binari adeguati, puoi creare cloni da lì. Se hai un cloud, sarà il provider cloud come Amazon o Google a farlo per te. Questo è il modo principale per clonare produzioni reali. È proprio così che effettuiamo il nostro schieramento.
- L'ultimo modo è adatto per ricerche, quando si desidera comprendere come funzioni un certo aspetto di Postgres. È pgbench. Puoi generare usando pgbench. È semplicemente un'opzione "db-pgbench". Gli dici quale scala. E tutto sarà 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 la emulazione può essere fatta prima di tutto in questo modo. Dobbiamo raccogliere tutti i log. E questo è doloroso. Ti mostrerò perché. E usando pgreplay, che è integrato in Nancy, lo riproduciamo.
- Oppure un'altra opzione. Il cosiddetto carico artigianale, che realizziamo con un certo impegno. Analizzando il nostro carico attuale sul sistema live, estraiamo i gruppi di query principali. E usando pgbench possiamo emulare questo carico in laboratorio.

- Oppure dobbiamo eseguire un certo SQL, vale a dire verifichiamo qualche migrazione, creiamo un indice, eseguiamo ANALAZE. E vediamo cosa c'era prima e dopo il vacuum. In generale, qualsiasi SQL.
- O cambiamo uno o più parametri nella configurazione. Possiamo chiedere di controllare, ad esempio, 100 valori su Amazon per il nostro database di un terabyte. E dopo qualche ora avrete il risultato. In genere, un database di un terabyte impiega diverse ore per avviarsi. Ma nello sviluppo esiste una patch, abbiamo la possibilità di fare una serie di test, cioè potete utilizzare lo stesso pgdata su lo stesso server e controllare. Postgres verrà riavviato e le cache verranno svuotate. E potete eseguire il carico.

- Arriva una directory con un sacco di file, a partire dagli snapshot pgstat***. E lì la cosa più interessante è 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 su checkpoint e su come i backend stesso gestiscono i buffer sporchi. È tutto interessante da vedere. Ad esempio, quando configuriamo shared_buffers, è molto interessante vedere quanto è stato espulso.
- Arrivano anche i log di Postgres. Due log – il log di preparazione e il log di esecuzione del carico.
- Una nuova funzionalità relativamente – i FlameGraphs.
- Inoltre, se avete utilizzato pgreplay o le varianti di pgbench per l'esecuzione del carico, avrete la loro output nativa. E vedrete latenza e TPS. Si potrà capire come l'hanno visto.
- Informazioni sul sistema.
- Controlli di base CPU e IO. Questo è più per gli istanze EC2 su Amazon, quando vuoi avviare 100 istanze identiche in stream e farci passare 100 esecuzioni diverse, avrai 10.000 esperimenti. E deve essere sicuro che non ti sia capitato un'istanza difettosa, che è già sotto pressione da qualcun altro. Su quel hardware ci sono altre attività in corso e le risorse scarseggiano. È meglio scartare tali risultati. E con l'aiuto di sysbench di Alexey Kopytov facciamo alcuni brevi controlli, che arriveranno e possono essere confrontati con altri, cioè capirete come si comporta la CPU e come si comporta l'IO.

Quali sono le complessità tecniche nell'esempio di diverse aziende?

Supponiamo che vogliamo ripetere un carico reale usando i log. È un'ottima idea se è stato scritto su Open Source pgreplay. Lo utilizziamo. Ma, affinché funzioni bene, devi abilitare il logging completo delle query con i parametri e i timing.
Ci sono alcune difficoltà riguardo a duration e timestamp. Tralasceremo tutti questi dettagli. La domanda principale è: puoi permettertelo o no?

Il problema è che potrebbe non essere disponibile. Devi prima di tutto capire quale flusso verrà registrato nel log. Se hai pg_stat_statements, puoi capire a grandi linee quanti byte verranno scritti al secondo con questa query (il link sarà disponibile nelle diapositive).
Guardiamo la lunghezza della query. Trascuriamo il fatto che non ci sono parametri, ma sappiamo la lunghezza della query e sappiamo quante volte al secondo è stata eseguita. In questo modo possiamo stimare quanti byte al secondo. Potremmo sbagliarci di due volte, ma capiremo sicuramente l'ordine di grandezza in questo modo.
Possiamo vedere che questa query viene eseguita 802 volte al secondo. E vediamo che bytes_per sec – 300 kB/s verranno scritti più o meno. E, di norma, possiamo permetterci questo flusso.

Ma! Il fatto è che ci sono diversi sistemi di registrazione. E per impostazione predefinita le persone di solito usano «syslog».

E se hai syslog, puoi avere un'immagine del genere. Prenderemo pgbench, attiveremo la registrazione delle query e vedremo cosa succede.

Senza registrazione – questa è la colonna a sinistra. Ottenevamo 161.000 TPS. Con syslog – su Ubuntu 16.04 su Amazon otteniamo 37.000 TPS. E se cambiamo a due altri metodi di registrazione, la situazione migliora notevolmente. Cioè, ci aspettavamo un calo, ma non così tanto.

E su CentOS 7, dove è coinvolto anche journald, che trasforma i log in formato binario per una ricerca più comoda, là è un vero disastro, perdiamo 44 volte in TPS.

E questo è ciò con cui convivono le persone. E spesso nelle aziende, soprattutto nelle grandi, è molto difficile cambiarlo. Se puoi allontanarti da syslog, allora ti prego di farlo.

- Valuta IOPS e flusso di scrittura.
- Controlla il tuo sistema di registrazione.
- Se il carico previsto è eccessivo, prendi in considerazione l'opzione del campionamento.

Abbiamo pg_stat_statements. Come ho detto, deve esserci assolutamente. E possiamo prendere e descrivere ogni gruppo di query in modo speciale in un file. E poi possiamo utilizzare una funzione molto utile in pgbench – la possibilità di fornire diversi file con l'opzione «-f».
Lui comprende molto «-f». E si può dire usando «@» alla fine, quale quota ognuno dei file dovrebbe avere. Cioè, possiamo dire che questo deve essere eseguito nel 10% dei casi, e questo nel 20%. E questo ci avvicinerà a ciò che vediamo in produzione.

E come capiremo cosa abbiamo in produzione? Qual è la quota e cosa riguarda? Qui ci allontaniamo un po'. Abbiamo un altro prodotto . Anche questo è basato su Open Source. E attualmente lo stiamo sviluppando attivamente.
È nato per ragioni un po' diverse. A causa del fatto che il monitoraggio è insufficiente. Cioè, arrivi, guardi il database, vedi i problemi esistenti. E, di solito, fai un controllo di salute. Se sei un DBA esperto, fai un controllo di salute. Hai esaminato l'uso degli indici, ecc. Se hai OKmeter, va benissimo. È un ottimo monitoraggio per Postgres. OKmeter.io – per favore, installalo, è tutto fatto molto bene. È a pagamento.
Se non ce l'hai, di solito non hai molto. Nel monitoraggio di solito ci sono CPU, IO e questo con riserve, e basta. E a noi serve di più. Dobbiamo vedere come funziona l'autovacuum, come funziona il checkpoint, in IO dobbiamo separare il checkpoint dal bgwriter e dai backend, ecc.
Il problema è che quando aiuti una grande azienda, non possono implementare rapidamente qualcosa. Non riescono ad acquistare rapidamente OKmeter. Magari lo compreranno fra sei mesi. Non possono installare rapidamente alcuni pacchetti.
E ci è venuta l'idea che avevamo bisogno di uno strumento speciale che non richieda alcuna installazione, cioè non dovete installare nulla in produzione. Lo installi sul tuo laptop, o su un server di osservazione, da cui eseguirai. E analizzerà molte cose: sia il sistema operativo, che il file system, e lo stesso Postgres, facendo alcune semplici query che possono essere eseguite direttamente in produzione senza problemi.
L'abbiamo chiamato Postgres-checkup. Se parliamo in termini medici, è un controllo della salute regolare. Se parliamo di automobile, è come il tagliando. Fai un tagliando alla tua auto ogni sei mesi o un anno, a seconda del modello. E fai un tagliando per il tuo database? Cioè, fai una ricerca approfondita regolarmente? È necessario farlo. Se fai backup, fai anche un checkup, è altrettanto importante.
E abbiamo uno strumento del genere. Ha iniziato a nascere attivamente solo tre mesi fa. È ancora giovane, ma ha già molte funzionalità.

Raccogliamo i gruppi di query più "influenti" – report K003 in Postgres-checkup
E lì c'è un gruppo di report K. Al momento ci sono tre report. E c'è questo report K003. Lì troviamo il vertice di pg_stat_statements, ordinato per total_time.
Quando ordiniamo i gruppi di query per total_time, vediamo in cima un gruppo che carica di più il nostro sistema, cioè consuma un maggior numero di risorse. Perché chiamo gruppi di query? Perché abbiamo scartato i parametri. Non si tratta più di query, ma di gruppi di query, cioè sono astratti.
E se ottimizziamo dall'alto verso il basso, alleggeriamo le nostre risorse e ritardiamo il momento in cui dobbiamo fare un upgrade. Questo è un ottimo modo per risparmiare denaro.
Forse non è il modo migliore in termini di cura degli utenti, perché potremmo non vedere casi rari, ma molto frustranti, in cui una persona ha aspettato 15 secondi. In totale, sono così rari che non li vediamo, ma ci occupiamo delle risorse.

Cosa è successo in questa tabella? Abbiamo effettuato due snapshot. Postgres_checkup ti fornirà la delta per ogni metrica: total-time, calls, rows, shared_blks_read, ecc. Ecco, ha calcolato la delta. Un grande problema di pg_stat_statements è che non ricorda quando è stato resettato. Se pg_stat_database lo ricorda, pg_stat_statements non lo fa. Vedi che c'è il numero 1.000.000, ma non sappiamo da dove abbiamo contato.

E qui lo sappiamo, abbiamo due snapshot. Sappiamo che la delta in questo caso era di 56 secondi. Un intervallo molto piccolo. Ordinato per total_time. E poi possiamo differenziare, cioè dividiamo tutte le metriche per la duration. Se dividiamo ogni metrica per la duration, avremo il numero di chiamate al secondo.
Successivamente, total_time per secondo è la mia metrica preferita. Si misura in secondi, al secondo, cioè quanti secondi ha impiegato il nostro sistema per eseguire questo gruppo di query al secondo. Se vedi più di un secondo al secondo, significa che avevi bisogno di più di un core. È una metrica molto utile. Puoi capire che questa persona, ad esempio, ha bisogno di almeno tre core.
Questo è il nostro segreto, non l'ho mai visto da nessuna parte. Fai attenzione: è una cosa molto semplice – secondo per secondo. A volte, quando hai CPU al 100 %, si tratta di mezz'ora al secondo, cioè hai dedicato mezz'ora solo a queste query.
In seguito vediamo righe al secondo. Sappiamo quante righe al secondo sono state restituite.
E c'è anche una cosa interessante. Quante shared_buffers al secondo abbiamo letto dallo stesso shared_buffers. I colpi erano già lì, e le righe le abbiamo prese dalla cache del sistema operativo, oppure dal disco. La prima opzione è veloce, mentre la seconda può essere veloce, ma non sempre, dipende dalla situazione.
E il secondo modo di differenziare è dividere il numero di richieste in questo gruppo. Nella seconda colonna avrai sempre una richiesta divisa per richiesta. E poi diventa interessante: quanti millisecondi sono stati in questa richiesta. Sappiamo come si comporta mediamente questa richiesta. Ogni richiesta ha richiesto 101 millisecondi. Questa è una metrica tradizionale di cui abbiamo bisogno per comprendere.
Quante righe ogni richiesta ha restituito mediamente. Vediamo che questo gruppo restituisce 8. Quante ne ha prese mediamente dalla cache e lette. Vediamo che tutto è stato memorizzato in cache in modo eccellente. Solo hit per il primo gruppo.
E la quarta sotto-stringa in ogni riga è la percentuale del totale. Abbiamo chiamate. Supponiamo 1.000.000. E possiamo capire quale contributo porta questo gruppo. Vediamo che in questo caso il primo gruppo contribuisce con meno dello 0,01%. Cioè è così lento che non lo vediamo nel quadro generale. E il secondo gruppo porta il 5% delle chiamate. Cioè il 5% di tutte le chiamate è questo secondo gruppo.
Anche per total_time è interessante. Abbiamo speso il 14% del tempo totale per il primo gruppo di richieste. E l'11% per il secondo, e così via.
Non scenderò nei dettagli, ma ci sono delle sottigliezze. Mostriamo un errore dall'alto, perché quando confrontiamo, gli snapshot possono sfuggire, cioè alcune richieste possono mancare nel secondo e potrebbero non essere presenti, mentre altre possono apparire. E calcoliamo l'errore lì. Se vedi 0, va bene. Significa che non ci sono errori. Se la misura dell'errore è fino al 20%, va bene.

In seguito torniamo al nostro argomento. Dobbiamo generare workload. Andiamo dall'alto verso il basso, finché non raggiungiamo l'80% o il 90%. Di solito sono 10-20 gruppi. E facciamo dei file per pgbench. Lì usiamo random. A volte questo, sfortunatamente, non funziona. E nella versione 12 di Postgres ci saranno più opportunità per utilizzare questo approccio.
E così continuiamo a raccogliere l'80-90 % del total_time. Cosa dobbiamo inserire dopo «@»? Guardiamo le chiamate, vediamo quanti sono i percentuali e capiamo che qui dobbiamo avere una certa percentuale. 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 sottostringhe. Questa è la caratteristica del nostro carico. Guarda la seconda colonna e la seconda sottostringa. Vediamo che è circa un secondo e mezzo al secondo, cioè se ci sono due core, andrà bene. Sarà circa il 75 % di carico. E funzionerà in questo modo. Se avremo 10 core, saremo davvero tranquilli. In questo modo possiamo valutare le risorse.
K002 è quello che io chiamo classi di richieste, cioè SELECT, INSERT, UPDATE, DELETE. E a parte SELECT FOR UPDATE, perché blocca.
E qui possiamo concludere che i SELECT normali letti sono il 82 % di tutte le chiamate, ma allo stesso tempo sono il 74 % del total_time. Cioè sono molto invocati, ma consumano meno risorse.

E torniamo alla domanda: «Come possiamo scegliere correttamente gli shared_buffers?». Osservo che la maggior parte dei benchmark sono costruiti sull'idea – vediamo quale sarà il throughput, cioè quale sarà la capacità di elaborazione. Essa di solito viene misurata in TPS o QPS.
E cerchiamo di estrarre il massimo dalla macchina grazie ai parametri di ottimizzazione per ottenere quante più transazioni al secondo possibile. Qui sono precisamente 311 al secondo per SELECT.

Ma nessuno va al lavoro e torna a casa in macchina a tutta velocità. Sarebbe sciocco. E così anche con i database. Non dovremmo viaggiare a tutta velocità, anzi, nessuno lo fa. Nessuno vive in produzione con il 100% di CPU. Anche se, forse, qualcuno lo fa, ma non è una buona cosa.
L'idea è che di solito viaggiamo al 20% delle nostre capacità, preferibilmente non oltre il 50%. E cerchiamo di ottimizzare il tempo di risposta per i nostri utenti prima di tutto. Cioè, dobbiamo muovere le nostre mani in modo che ci sia la minima latenza a una velocità del 20%, in modo ipotetico. Questa è un'idea che cerchiamo di utilizzare nei nostri esperimenti.

E per concludere le raccomandazioni:
- Assicurati di creare un Database Lab.
- Se possibile, falla on demand, in modo che si possa avviare per un certo periodo di tempo – giocare e poi scartare. Se hai cloud, allora è ovvio, cioè avere molti standing.
- Siate curiosi. E se qualcosa non va, verificate con esperimenti come si comporta. Potete usare Nancy per imparare e per controllare come funziona il database.
- E puntate a un tempo di risposta minimo.
- E non abbiate paura del codice sorgente di Postgres. Quando lavorate con il codice sorgente, dovete conoscere l'inglese. Ci sono molti commenti, tutto è spiegato.
- E controllate la salute del database regolarmente, almeno una volta ogni tre mesi a mano, oppure usando Postgres-checkup.

Domande
Grazie mille! È una cosa molto interessante.
Due cose.
Sì, due cose. Solo che non ho capito completamente. Quando lavoriamo con Nancy, possiamo modificare solo un parametro o un intero gruppo?
Abbiamo un parametro di delta-config. Potete modificarne quanti ne volete. Ma bisogna capire che quando cambiate molte cose, potreste trarre conclusioni sbagliate.
Sì. Perché ho chiesto? Perché è difficile condurre esperimenti quando hai solo un parametro. Lo modifichi, guardi come funziona. Lo imposti. Poi inizi con il successivo.
Si può modificare più di un parametro contemporaneamente, ma dipende dalla situazione, ovviamente. Ma è meglio testare una sola idea. 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. È emersa l'idea che fosse necessario utilizzare la dicotomia per capire e trovare in cosa consiste la differenza. Si possono immediatamente rendere uguali metà dei parametri, poi un quarto e così via. È tutto flessibile.
E c'è un'altra domanda. Il progetto è giovane e si sta sviluppando. La documentazione è già pronta, c'è una descrizione dettagliata?
Ho messo un link per la descrizione dei parametri. C'è. Ma c'è ancora molto che manca. Sto cercando alleati. E li trovo quando parlo. È fantastico. Qualcuno già lavora con me, qualcun altro ha aiutato e ha fatto qualcosa. E se questa tematica vi interessa, date un feedback su cosa manca.
Quando avremo il laboratorio, potrebbe esserci un feedback. Vedremo. Grazie!
Salve! Grazie per la presentazione! Ho visto che c'è supporto per Amazon. È prevista la supporto per GSP?
Buona domanda. Abbiamo iniziato a lavorare. E al momento abbiamo congelato, perché vogliamo risparmiare. Cioè, c'è supporto tramite run on localhost. Puoi creare un'istanza e lavorare localmente. A proposito, lo facciamo così. In Getlab faccio così, lì su GSP. Ma fare proprio questo orchestrazione, al momento non vediamo senso, perché Google non ha spot a prezzi bassi. Ci sono ??? istanze, ma hanno delle limitazioni. Prima di tutto, hanno sempre solo uno sconto del 70% e lì non si può giocare con il prezzo. Gli spot aumentiamo il prezzo del 5-10%, per ridurre la probabilità di essere eliminati. Cioè, negli spot risparmi, ma possono portarteli via in qualsiasi momento. Se fai il prezzo un po' più alto rispetto agli altri, verrai eliminato più tardi. Google ha una specifica del tutto diversa. E c'è un'altra limitazione molto sgradevole: vivono solo per 24 ore. E a volte vogliamo eseguire esperimenti per 5 giorni. Ma negli spot questo è possibile, a volte gli spot vivono per mesi.
Salve! Grazie per la relazione! Hai menzionato il checkup. Come calcolate gli errori stat_statements?
Ottima domanda. Posso mostrarti e spiegarti molto in dettaglio. Brevemente, guardiamo come è cambiato il gruppo di richieste: quante sono crollate e quante nuove sono apparse. E poi osserviamo due metriche: total_time e calls, e quindi ci sono due errori. E vediamo quale contributo hanno i gruppi modificati. Ci sono due sottogruppi: quello che è andato via e quello che è tornato. Controlliamo quale sia il loro contributo all'insieme.
Ma non hai paura che venga elaborato due o tre volte tra i snapshot?
Cioè, si sono registrati di nuovo o come?
Ad esempio, questa richiesta è già stata espulsa una volta, poi è tornata ed è stata nuovamente espulsa, poi ancora è tornata ed è stata espulsa di nuovo. E qui hai fatto qualche calcolo, e dove sono tutte queste informazioni?
Buona domanda, dobbiamo controllare.
Ho fatto un lavoro simile. Certo, era più semplice, l'ho fatto da solo. Ma ho dovuto resettare, fare il reset stat_statements e orientarmi al momento dello snapshot, per verificare che ci fosse meno di una certa quota, che in ogni caso non fosse arrivato al limite di quanto possa accumulare stat_statements. E mi oriento sul fatto che, molto probabilmente, non è stato espulso nulla.
Sì-sì.
Ma come fare diversamente in modo affidabile, non riesco a capire.
Purtroppo, non ricordo esattamente se utilizziamo il testo della richiesta o l'queryid con pg_stat_statements e ci orientiamo su quello. Se ci orientiamo su queryid, allora, in teoria, confrontiamo cose comparabili.
No, può essere espulso più volte tra gli snapshot e tornare di nuovo.
Con lo stesso ID?
Sì.
Lo studieremo. Bella domanda. Dobbiamo analizzarlo. Ma per ora, quello che vediamo è che abbiamo o 0 scritto...
È ovviamente un caso raro, ma sono rimasto sorpreso quando ho scoperto che stat_statements può espellere.
In Pg_stat_statements può esserci di tutto. Abbiamo riscontrato che se track_utility è attivato, anche i tuoi set vengono tracciati.
Sì, certo.
E se hai Java Hibernate, che è casuale, allora inizia a bloccarsi la tabella hash. E non appena disattivi un'applicazione molto pesante, hai 50-100 gruppi. E lì tutto diventa più o meno stabile. Uno dei modi per combattere questo è aumentare pg_stat_statements.max.
Sì, ma bisogna sapere di quanto. E bisogna monitorarlo. Io lo faccio così. Cioè, ho pg_stat_statements.max e vedo che al momento dello snapshot non ho raggiunto il 70%. Bene, significa che non abbiamo perso nulla. Facciamo il reset. E accumuliamo di nuovo. Se nel prossimo snapshot siamo sotto il 70%, allora probabilmente non abbiamo perso nulla di nuovo.
Sì. Attualmente, per impostazione predefinita, è 5.000. E a molti di loro basta questo.
Di solito sì.
Video:

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

Fonte: habr.com
