{"id":81089,"date":"2020-05-11T01:42:24","date_gmt":"2020-05-10T23:42:24","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov"},"modified":"2020-05-11T01:42:24","modified_gmt":"2020-05-10T23:42:24","slug":"tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","title":{"rendered":"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal'nikov","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>Ti invitiamo a consultare la trascrizione della relazione di inizio 2016 di Andrey Sal'nikova \"Errori tipici nelle applicazioni che portano a bloat in postgresql\"<\/strong><\/p>\n<p><\/p>\n<p>In questa presentazione, analizzer\u00f2 gli errori principali nelle applicazioni che si verificano durante la fase di progettazione e scrittura del codice. Mi concentrer\u00f2 solo su quegli errori che portano a bloat in PostgreSQL. Di norma, questo segna l'inizio della fine delle prestazioni del vostro sistema complessivo, anche se inizialmente non sembrava esserci alcuna indicazione di ci\u00f2.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/a9e199bfe2e01c76966b32868790f8f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Sono lieto di darvi il benvenuto! Questa presentazione non \u00e8 cos\u00ec tecnica come quella precedente del mio collega. \u00c8 rivolta principalmente agli sviluppatori di sistemi backend, dato che abbiamo un numero abbastanza elevato di clienti. E tutti loro commettono gli stessi errori. Di questi parler\u00f2. Spiegher\u00f2 quali conseguenze fatali e negative derivano da tali errori. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/c6c84dbafc595ae3068cd8bf804ccee7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Perch\u00e9 si commettono errori? Gli errori si verificano per due motivi: per incuria, pensando 'forse andr\u00e0 bene' e per la mancanza di conoscenza di alcuni meccanismi che si verificano a livello tra il database e l'applicazione, cos\u00ec come all'interno del database stesso. <\/p>\n<p><\/p>\n<p>Vi presenter\u00f2 tre esempi con immagini terribili di come tutto sia andato male. In breve, spiegher\u00f2 il meccanismo che sta dietro a questi problemi. E come affrontarli quando si presentano, e quali metodi preventivi utilizzare per evitare errori. Parler\u00f2 di strumenti utili e fornir\u00f2 link interessanti. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/b0230d992f5b44f0e542df2e4b4d526f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ho usato un database di test, dove avevo due tabelle. Una tabella con le fatture dei clienti, l'altra con le operazioni su queste fatture. E con una certa periodicit\u00e0 aggiorniamo i saldi su queste fatture.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/1d2a21278b095b07546e1bb870819dbf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dati iniziali della tabella: \u00e8 piuttosto piccola, 2 MB. Il tempo di risposta del database e in particolare della tabella \u00e8 molto buono. E un carico piuttosto elevato \u2013 2.000 operazioni al secondo sulla tabella.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/dea5a4b1ac7952f8cfed0e2e1cfc10dd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E lungo questa presentazione vi mostrer\u00f2 grafici, per rendere evidente cosa stia accadendo. Ci saranno sempre 2 diapositive con grafici. La prima diapositiva mostra quello che accade complessivamente sul server. <\/p>\n<p><\/p>\n<p>In questa situazione vediamo che effettivamente abbiamo una tabella di piccole dimensioni. L'indice \u00e8 piccolo, di 2 MB. Questo \u00e8 il primo grafico a sinistra. <\/p>\n<p><\/p>\n<p>Il tempo medio di risposta del server \u00e8 anche stabile e ridotto. Questo \u00e8 il grafico in alto a destra. <\/p>\n<p><\/p>\n<p>Il grafico in basso a sinistra mostra le transazioni pi\u00f9 lunghe. Possiamo vedere che le transazioni vengono eseguite rapidamente. E l'autovacuum non sta ancora funzionando, perch\u00e9 questo \u00e8 stato solo un test iniziale. Successivamente funzioner\u00e0 e sar\u00e0 utile per noi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/9e9b46acd9a878ff70ca4a7850adff09.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>La seconda diapositiva sar\u00e0 sempre dedicata alla tabella in esame. In questa situazione, aggiorniamo costantemente i saldi sui conti dei clienti. Possiamo vedere che il tempo medio di risposta per l'operazione di aggiornamento \u00e8 piuttosto buono, meno di un millisecondo. Possiamo notare che le risorse della CPU (questo \u00e8 il grafico in alto a destra) vengono consumate in modo uniforme e sono abbastanza basse. <\/p>\n<p><\/p>\n<p>Il grafico in basso a destra mostra quanta memoria operativa e di disco stiamo utilizzando mentre cerchiamo la riga che ci serve, prima di aggiornarla. E il numero di operazioni sulla tabella \u00e8 di 2.000 al secondo, come ho gi\u00e0 detto prima. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/84760d52716209b8dcfffb462c67a8e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E ora si verifica una tragedia. Per qualche motivo, si presenta una transazione lunga e dimenticata. Di solito, le ragioni sono piuttosto banali: <\/p>\n<p><\/p>\n<ul>\n<li>Una delle pi\u00f9 comuni \u00e8 che nel codice dell'applicazione abbiamo iniziato a contattare un servizio esterno. E questo servizio non risponde. Cio\u00e8, abbiamo aperto una transazione, apportato delle modifiche al database e ci siamo messi a controllare la posta o a utilizzare un altro servizio della nostra infrastruttura, e per qualche motivo non riceviamo risposta. E la nostra sessione \u00e8 rimasta in uno stato di attesa, non sapendo quando si risolver\u00e0.<\/li>\n<li>La seconda situazione \u00e8 quella in cui nel codice si \u00e8 verificata un'eccezione per qualche motivo. E non abbiamo gestito la chiusura della transazione nell'eccezione. Cos\u00ec abbiamo una sessione bloccata con una transazione aperta. <\/li>\n<li>E infine, un altro caso piuttosto comune \u00e8 il codice di bassa qualit\u00e0. Alcuni framework aprono una transazione. Questa rimane aperta, e potresti non sapere che \u00e8 attiva nell'applicazione. <\/li>\n<\/ul>\n<p><\/p>\n<p>A cosa portano queste situazioni? <\/p>\n<p><\/p>\n<p>Portano al fatto che le tabelle e gli indici iniziano a espandersi bruscamente. Questo \u00e8 esattamente l'effetto bloat. Per il database, questo si tradurr\u00e0 in un notevole aumento del tempo di risposta, e un aumento del carico sul server del database. Di conseguenza, l'applicazione ne risentir\u00e0. Perch\u00e9 se nel codice impiegavi 10 millisecondi per una richiesta al database e 10 millisecondi per la tua logica, la tua funzione si eseguiva in 20 millisecondi. Ma ora la tua situazione sar\u00e0 molto pi\u00f9 critica. <\/p>\n<p><\/p>\n<p>E vediamo cosa sta succedendo. Il grafico in basso a sinistra mostra che abbiamo una transazione lunga. Se guardiamo al grafico in alto a sinistra, vediamo che la dimensione della tabella \u00e8 passata da due megabyte a ben 300 megabyte. Tuttavia, la quantit\u00e0 di dati nella tabella non \u00e8 cambiata, il che significa che c'\u00e8 una notevole quantit\u00e0 di dati inutili.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/b1947f6487e440a770a1251a955e62d2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Anche la situazione riguardante il tempo medio di risposta del server \u00e8 cambiata drasticamente. Tutte le richieste al server hanno cominciato a rallentare notevolmente. Inoltre, sono stati avviati processi interni di Postgres, come l\u2019autovacuum, che tentano di eseguire operazioni e consumano risorse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/8e91f035d1dd04e72e842d714cc611a5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cosa sta succedendo alla nostra tabella? La situazione \u00e8 simile. Il tempo medio di risposta per la tabella \u00e8 aumentato notevolmente. Se osserviamo i consumi di risorse, notiamo un forte aumento del carico sulla CPU. Questo \u00e8 mostrato nel grafico in alto a destra. \u00c8 aumentato perch\u00e9 la CPU deve esaminare un gran numero di righe inutili nella ricerca di quella necessaria. Questo \u00e8 illustrato nel grafico in basso a destra. Di conseguenza, il numero di chiamate al secondo ha cominciato a diminuire drasticamente, poich\u00e9 il database non riesce a gestire lo stesso numero di richieste. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/424685ce852bc5f3ef77151f8d3d7289.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dobbiamo tornare a una situazione normale. Ci informiamo online e scopriamo che le transazioni lunghe causano problemi. Identifichiamo e interrompiamo questa transazione. E le cose tornano a funzionare normalmente. Tutto riprende a funzionare come dovrebbe. <\/p>\n<p><\/p>\n<p>Ci siamo calmati, ma dopo un po' iniziamo a notare che l'applicazione non funziona come prima dell'interruzione. Le richieste continuano a essere elaborate pi\u00f9 lentamente, significativamente pi\u00f9 lentamente. Nella mia esperienza specifica, il rallentamento \u00e8 stato di circa il 50-100%. Il carico sul server \u00e8 anche superiore a quello che era prima dell'interruzione. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/ee3037719a31f8d18fc42745716c4da5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E la domanda \u00e8: \u00abCosa sta succedendo al database in questo momento?\u00bb. Ecco cosa accade. Nel grafico delle transazioni vedete che \u00e8 fermo e in effetti non ci sono transazioni lunghe. Ma la dimensione della tabella \u00e8 aumentata drammaticamente durante l'interruzione e non \u00e8 diminuita da allora. Il tempo medio del database si \u00e8 stabilizzato. E le risposte sembrano avere una velocit\u00e0 accettabile per noi. L\u2019autovacuum \u00e8 diventato pi\u00f9 attivo e ha iniziato a elaborare una maggiore quantit\u00e0 di dati. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/f6205242c4024dc3ed4cade5844dbf76.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Per quanto riguarda la tabella dei conti, dove stiamo modificando i saldi: il tempo di risposta per le richieste sembra tornare alla normalit\u00e0. Ma in realt\u00e0 \u00e8 aumentato di circa il 50%.<\/p>\n<p><\/p>\n<p>Per quanto riguarda il carico sulla CPU, vediamo che non \u00e8 tornato ai livelli desiderati pre-interruzione. Le ragioni si possono rintracciare nel grafico in basso a destra, dove si osserva l'uso di una certa quantit\u00e0 di memoria. Per cercare la riga corretta, stiamo sprecando risorse del server Database nel setacciare dati inutili. Il numero di transazioni al secondo si \u00e8 stabilizzato. <\/p>\n<p><\/p>\n<p>Insomma, va bene, ma la situazione \u00e8 peggiore di prima. C'\u00e8 una chiara degradazione del database come conseguenza della nostra applicazione che interagisce con esso. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/0dfc9cd453fd84bc639ffd99cf189fd2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Per capire cosa sta succedendo, se non eravate presenti alla presentazione precedente, ecco un po' di teoria. Teoria sul processo interno. Perch\u00e9 esiste l\u2019autovacuum e cosa fa?<\/p>\n<p><\/p>\n<p>In sintesi, in un certo momento abbiamo una tabella. La tabella contiene righe. Queste righe possono essere attive, vive, necessarie al momento. Nell'immagine sono contrassegnate in verde. Ci sono anche righe morte, che hanno gi\u00e0 eseguito il loro compito, sono state aggiornate e hanno nuovi record. Queste righe sono contrassegnate come non pi\u00f9 rilevanti per il database, ma rimangono nella tabella a causa delle peculiarit\u00e0 di Postgres.<\/p>\n<p><\/p>\n<p>Perch\u00e9 \u00e8 necessario l\u2019autovacuum? A un certo punto, l\u2019autovacuum accede al database e chiede: \u00abPer favore, dammi l'id della transazione pi\u00f9 vecchia attualmente aperta nel database\u00bb. Il database restituisce questo id. Basandosi su questo, l\u2019autovacuum esamina le righe nella tabella e se vede che alcune righe sono state modificate da transazioni molto pi\u00f9 vecchie, ha il diritto di contrassegnarle come righe che possiamo riutilizzare in futuro, scrivendo nuovi dati al loro interno. Questo \u00e8 un processo in background.<\/p>\n<p><\/p>\n<p>Nel frattempo, continuiamo a lavorare con il database, apportando delle modifiche alle tabelle. E a queste righe, che possiamo riutilizzare, scriviamo nuovi dati. In questo modo, abbiamo un ciclo continuo: continuamente si formano righe morte e vecchie, e sopra di esse scriviamo nuove righe necessarie. Questo \u00e8 uno stato normale per il funzionamento di PostgreSQL.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/98dd4451a7ca5f418775f72822c2840c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cosa \u00e8 successo durante l'interruzione? Come si \u00e8 svolto questo processo?<\/p>\n<p><\/p>\n<p>Abbiamo avuto una tabella in uno stato vario, con alcune righe vive e altre morte. \u00c8 intervenuto l'auto-vacuum. Ha chiesto al database qual \u00e8 la nostra transazione pi\u00f9 antica e qual \u00e8 il suo id. Ha ottenuto questo id, che pu\u00f2 risalire a ore fa o a dieci minuti fa. Questo dipende da quanto \u00e8 alta la carico nel tuo database. E ha iniziato a cercare righe che potesse contrassegnare come riutilizzabili. Ma non ha trovato righe in nostra tabella. <\/p>\n<p><\/p>\n<p>Ma nel frattempo continuiamo a lavorare con la tabella. Stiamo modificando, aggiornando i dati. E cosa pu\u00f2 fare il database in quel momento? Non ha altra scelta che scrivere nuove righe alla fine della tabella esistente. Cos\u00ec, la dimensione della tabella comincia ad aumentare. <\/p>\n<p><\/p>\n<p>In realt\u00e0 abbiamo bisogno di righe verdi per lavorare. Ma durante un problema di questo tipo si verifica che la percentuale di righe verdi \u00e8 molto bassa in tutta la tabella. <\/p>\n<p><\/p>\n<p>E quando eseguiamo una query, il database deve scorrere tutte le righe: sia quelle rosse che quelle verdi, per trovare la riga giusta. L'effetto dell'ingrossamento della tabella con dati inutili si chiama \u00abbloat\u00bb, che consuma anche il nostro spazio su disco. Ricordi, era 2 MB e ora \u00e8 300 MB? Ora cambia megabyte in gigabyte e perderai rapidamente tutte le tue risorse di disco.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/fe7cb6b5c99610744ebcfe5ad7235d1e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Quali possono essere le conseguenze per noi? <\/p>\n<p><\/p>\n<ul>\n<li>Nel mio esempio, la tabella e l'indice sono cresciuti 150 volte. Alcuni dei nostri clienti hanno vissuto casi pi\u00f9 gravi, dove lo spazio su disco ha cominciato a scarseggiare. <\/li>\n<li>La dimensione delle tabelle non diminuir\u00e0 mai da sola. L'auto-vacuum in alcuni casi pu\u00f2 tagliare la coda della tabella, se ci sono solo righe morte. Ma poich\u00e9 avviene un costante ricambio, una riga verde pu\u00f2 rimanere sospesa alla fine e non essere aggiornata, mentre tutte le altre saranno scritte all'inizio della tabella. Ma questo \u00e8 un evento tanto improbabile che non si pu\u00f2 contare su una riduzione naturale della dimensione della tabella. <\/li>\n<li>Il database deve scandire un accumulo di righe inutili. E noi stiamo consumando risorse di disco, risorse della CPU e energia. <\/li>\n<li>E questo influisce direttamente sulla nostra applicazione, perch\u00e9 se inizialmente impiegavamo 10 millisecondi per una query e 10 millisecondi per il nostro codice, durante l'emergenza abbiamo cominciato a impiegare un secondo per la query e 10 millisecondi per il codice, cio\u00e8 la prestazione dell'applicazione \u00e8 diminuita di un ordine di grandezza. E quando l'emergenza \u00e8 stata risolta, abbiamo cominciato a spendere 20 millisecondi per la query e 10 millisecondi per il codice. Significa che abbiamo comunque perso un 50% di prestazione. E tutto questo a causa di una transazione che \u00e8 rimasta sospesa, forse per nostra colpa. <\/li>\n<li>E la domanda \u00e8: \u00abCome possiamo tornare indietro?\u00bb, affinch\u00e9 tutto funzioni di nuovo e le query siano veloci come prima dell'emergenza. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/1bf46e8cd9b28ca2862f978f2ca85819.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Per questo esiste un certo ciclo di lavori da eseguire. <\/p>\n<p><\/p>\n<p>Innanzitutto, dobbiamo identificare le tabelle problematiche che si sono gonfiate. Comprendiamo che per alcune tabelle le scritture avvengono pi\u00f9 attivamente, per altre meno. E per questo si utilizza l'estensione <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/pgstattuple.html\">pgstattuple<\/a><\/noindex>. Installando questa estensione, puoi scrivere query che ti aiuteranno a individuare le tabelle che si sono gonfiate significativamente. <\/p>\n<p><\/p>\n<p>Dopo aver trovato queste tabelle, \u00e8 necessario comprimerle. Per questo ci sono gi\u00e0 strumenti. Nella nostra azienda utilizziamo tre strumenti. Il primo \u00e8 il VACUUM FULL integrato. \u00c8 severo, duro e spietato, ma a volte \u00e8 molto utile. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">Pg_repack<\/a><\/noindex> e <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">pgcompacttable<\/a><\/noindex> sono utilit\u00e0 di terze parti per comprimere le tabelle. E trattano il database in modo pi\u00f9 delicato. <\/p>\n<p><\/p>\n<p>Vengono utilizzati a seconda di cosa ti risulta pi\u00f9 comodo. Ma di questo parler\u00f2 alla fine. L'importante \u00e8 che ci siano tre strumenti. Hai delle scelte. <\/p>\n<p><\/p>\n<p>Dopo aver sistemato tutto e aver verificato che sia andato tutto bene, dobbiamo sapere come prevenire questa situazione in futuro:<\/p>\n<p><\/p>\n<ul>\n<li>\u00c8 abbastanza facile prevenirla. \u00c8 necessario monitorare la durata delle sessioni sul Master-server. <strong>Le sessioni particolarmente pericolose sono in stato di idle in transaction<\/strong>. Queste sono quelle in cui hanno aperto una transazione, hanno fatto qualcosa e se ne sono andati o sono semplicemente rimaste sospese, perdersi nel codice. <\/li>\n<li>E per voi, come sviluppatori, \u00e8 importante testare il codice al momento di queste situazioni. Non \u00e8 difficile farlo. Sar\u00e0 un controllo utile. Eviterai un gran numero di problemi \u00abinfantili\u00bb legati a transazioni lunghe. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/d55465d96c4018db733954867d23aaba.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In questi grafici volevo mostrarti come \u00e8 cambiata la tabella e il comportamento del database dopo che ho eseguito un VACUUM FULL su questa tabella. Questo non \u00e8 in produzione.<\/p>\n<p><\/p>\n<p>La dimensione della tabella \u00e8 tornata rapidamente nella norma, a pochi megabyte. Questo non ha avuto un grande impatto sul tempo medio di risposta del server. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/cbb07ad24dba899395223d1ca25e438e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tuttavia, per la nostra tabella in esame, dove aggiornavamo i saldi, notiamo che il tempo medio di risposta per le query di aggiornamento dei dati \u00e8 diminuito a livelli pre-crisi. Anche le risorse richieste dal processore per eseguire questa query sono tornate a livelli pre-crisi. Il grafico in basso a destra mostra che ora troviamo esattamente la riga necessaria senza dover sfogliare un insieme di righe inutili presenti prima della compressione della tabella. Il tempo medio delle query \u00e8 rimasto pi\u00f9 o meno allo stesso livello. Tuttavia, questo potrebbe essere pi\u00f9 un errore del mio hardware.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/c1d90c5442e02fce209dc40e048a8ca2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Questa \u00e8 la prima storia. \u00c8 la pi\u00f9 comune e pu\u00f2 capitare a chiunque, indipendentemente dall'esperienza del cliente o dalla competenza dei programmatori. Prima o poi succede. <\/p>\n<p><\/p>\n<p>La seconda storia riguarda come distribuiamo il carico e ottimizziamo le risorse del server.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/cda421c554d1329107ddc935045cc1b9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Siamo gi\u00e0 cresciuti e ci siamo affermati. Comprendiamo che abbiamo una replica e sarebbe utile bilanciare il carico: scriviamo sul master e leggiamo dalla replica. Di solito, questa situazione si verifica quando vogliamo generare rapporti o ETL. E questo fa molto piacere al business. Vuole rapporti vari con una complessa analisi. <\/li>\n<li>I rapporti richiedono ore, poich\u00e9 un\u2019analisi complessa non pu\u00f2 essere elaborata in millisecondi. Noi, come bravi ragazzi, scriviamo codice. Effettuiamo inserimenti nell'applicazione, registrando i dati sul master e generando i rapporti sulla replica. <\/li>\n<li>Distribuiamo il carico. <\/li>\n<li>Tutto funziona alla perfezione. Siamo bravi. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/e94c8c492197a5015ac8aae79389a4c2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E come appare questa situazione? Sui grafici ho anche aggiunto la durata delle transazioni dalla replica. Tutti gli altri grafici riguardano solo il master server. <\/p>\n<p><\/p>\n<p>Nel frattempo, la mia tabella dei rapporti \u00e8 cresciuta. Ce ne sono di pi\u00f9. Notiamo che il tempo medio di risposta del server \u00e8 stabile. Vedo che sulla replica abbiamo una transazione lunga che dura 2 ore. Vedo anche il funzionamento tranquillo dell'autovacuum che elabora le righe morte. E va tutto bene. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/2da8acf098d12d6f146ab9b9dcb54b81.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In particolare, per la tabella in esame, continuiamo ad aggiornare i saldi. Anche noi abbiamo un tempo di risposta stabile per la query e un consumo di risorse costante. Tutto \u00e8 a posto. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/3621ef723017bac6fb635caf0a5f4de6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tutto va bene finch\u00e9 questi rapporti non iniziano a causare conflitti con la replica. E i conflitti si verificano con una certa periodicit\u00e0. <\/p>\n<p><\/p>\n<p>Ci rivolgiamo a Internet e iniziamo a leggere perch\u00e9 questo sta accadendo. E troviamo una soluzione. <\/p>\n<p><\/p>\n<p>La prima soluzione \u00e8 aumentare la latenza della replica. Sappiamo che il nostro rapporto richiede 3 ore. Impostiamo la latenza della replica a 3 ore. Avviamo il tutto, ma continuiamo a riscontrare problemi con rapporti che a volte falliscono. <\/p>\n<p><\/p>\n<p>Vogliamo che tutto sia perfetto. Approfondiamo la ricerca e troviamo una fantastica impostazione su internet: hot_standby_feedback. La attiviamo. L'hot_standby_feedback permette di ritardare l'operazione dell'autovacuum sul master. In questo modo, ci liberiamo completamente dai conflitti di replica e tutto funziona bene con i rapporti.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/ee3c315168bdd3f392d2e8a1c5861004.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E cosa succede nel frattempo con il master server? Il master server \u00e8 in crisi totale. In questo momento stiamo osservando i grafici, quando ho attivato entrambe queste impostazioni. Vediamo che la sessione sulla replica, in qualche modo, ha iniziato a influire sulla situazione del master server. Di fatto influisce, poich\u00e9 ha sospeso l'autovacuum che elimina le righe morte. La dimensione della tabella \u00e8 nuovamente schizzata in alto. Anche il tempo medio di esecuzione delle query sull'intero database \u00e8 aumentato. Gli autovacuum sono tornati a essere un po' stressati. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/980611dcce8b189dc50f422ffd3d2d72.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In particolare, nella nostra tabella vediamo che l'aggiornamento dei dati \u00e8 anch'esso schizzato in alto. Il consumo delle risorse della CPU \u00e8 aumentato notevolmente. Dobbiamo nuovamente esaminare un gran numero di righe morte e inutili. E il tempo di risposta per questa tabella e il numero di transazioni sono diminuiti. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/a648fd313a5dccf45f0056dc13c54263.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Come apparir\u00e0 questa situazione se non sappiamo di cosa stavo parlando prima?<\/p>\n<p><\/p>\n<ul>\n<li>Iniziamo a cercare problemi. Se abbiamo avuto problemi nella prima parte, sappiamo che potrebbe esserci una causa in una transazione lunga e andiamo sul master. Il problema \u00e8 sul master. Viene sovraccaricato. Si sta surriscaldando, con un carico medio che sfiora il centinaio. <\/li>\n<li>Le query rallentano, ma non vediamo transazioni lunghe. E non capiamo qual \u00e8 il problema. Non riusciamo a capire dove cercare. <\/li>\n<li>Controlliamo l'hardware del server. Potrebbe essersi rotto il RAID. Potrebbe esserci un banco di memoria guasto. Pu\u00f2 succedere di tutto. Ma no, i server sono nuovi, tutto funziona benissimo. <\/li>\n<li>Tutti corrono: amministratori, sviluppatori e il direttore. Niente sembra aiutare. <\/li>\n<li>E a un certo punto, inspiegabilmente, tutto inizia a sistemarsi da solo. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/7d4f6417bc5cb3cec33679d843c6661d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Sulla replica, nel frattempo, la richiesta \u00e8 stata elaborata ed \u00e8 andata. Abbiamo ricevuto il rapporto. L'attivit\u00e0 continua a essere soddisfacente. Come possiamo vedere, la nostra tabella \u00e8 di nuovo cresciuta e non sembra avere intenzione di ridursi. Nel grafico delle sessioni, ho lasciato un frammento di questa lunga transazione dalla replica, cos\u00ec potete valutare quanto tempo ci vuole affinch\u00e9 la situazione si stabilizzi. <\/p>\n<p><\/p>\n<p>La sessione \u00e8 andata. E solo dopo un po' di tempo il server torna pi\u00f9 o meno in ordine. E il tempo medio di risposta alle richieste sul Master-server torna alla normalit\u00e0. Perch\u00e9 finalmente l'autovacuum ha avuto la possibilit\u00e0 di pulire, contrassegnare queste righe morte. E ha iniziato a fare il suo lavoro. E tanto pi\u00f9 velocemente lo fa, tanto pi\u00f9 rapidamente torneremo alla normalit\u00e0.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/547d195e08de1566da818150a47218eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Per la tabella in cui aggiorniamo i saldi dei conti, osserviamo esattamente la stessa situazione. Anche il tempo medio di aggiornamento del conto si normalizza gradualmente. Le risorse utilizzate dal processore diminuiscono. E il numero di transazioni al secondo torna alla normalit\u00e0. Ma di nuovo alla normalit\u00e0, non come era prima dell'incidente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/29372a5e9124690931485a7aea65befc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In ogni caso, dobbiamo aspettarci un calo delle prestazioni come nel primo caso, da un una volta e mezza a due volte, e talvolta anche di pi\u00f9. <\/p>\n<p><\/p>\n<p>Sembra che abbiamo fatto tutto correttamente. Abbiamo distribuito il carico. L'hardware non \u00e8 inattivo. Abbiamo suddiviso le richieste in modo intelligente, ma comunque non \u00e8 andata come sperato. <\/p>\n<p><\/p>\n<ul>\n<li>Disattivare hot_standby_feedback? S\u00ec, in effetti, non \u00e8 consigliato attivarlo senza una valida motivazione. Perch\u00e9 questo parametro influisce direttamente sul Master-server e sospende il funzionamento dell'autovacuum l\u00ec. Se lo attivi su qualche replica e poi te ne dimentichi, potresti danneggiare il Master e avere problemi seri con l'applicazione. <\/li>\n<li>Aumentare max_standby_streaming_delay? S\u00ec, per i rapporti \u2013 \u00e8 cos\u00ec. Se hai un rapporto di tre ore e non vuoi che fallisca a causa dei conflitti di replica, puoi semplicemente aumentare il ritardo. Un rapporto lungo non richiede mai dati che sono stati appena inseriti nel database. Se \u00e8 un rapporto di tre ore, significa che lo stai eseguendo su un dato di un periodo anteriore. E per te, tre o sei ore di ritardo non fanno alcuna differenza, ma cos\u00ec garantirai rapporti stabili senza problemi di fallimenti. <\/li>\n<li>Naturalmente, \u00e8 necessario monitorare le sessioni lunghe sulle repliche, specialmente se hai deciso di attivare hot_standby_feedback su una replica. Perch\u00e9 pu\u00f2 succedere qualsiasi cosa. Hai dato quella replica a uno sviluppatore perch\u00e9 testasse delle richieste. Ha scritto una richiesta complessa. L'ha eseguita e se n'\u00e8 andato a bere un t\u00e8, mentre noi abbiamo avuto un Master sovraccarico. O abbiamo inserito l'applicazione sbagliata. Le situazioni sono varie. Le sessioni sulle repliche devono essere monitorate con la stessa attenzione che si riserva a quelle sul Master. <\/li>\n<li>E se hai richieste veloci e lunghe sulle repliche, in questo caso \u00e8 meglio suddividerle per distribuire il carico. Questo \u00e8 un riferimento al streaming_delay. Per le richieste veloci, avere una replica con un piccolissimo ritardo nella replica. Per le richieste di rapporti lunghi, avere una replica che pu\u00f2 ritardare di 6 ore o persino un giorno. \u00c8 una situazione del tutto normale. <\/li>\n<\/ul>\n<p><\/p>\n<p>Eliminiamo le conseguenze nello stesso modo:<\/p>\n<p><\/p>\n<ul>\n<li>Troviamo le tabelle gonfiate.<\/li>\n<li>E comprimiamo con lo strumento pi\u00f9 comodo che abbiamo a disposizione. <\/li>\n<\/ul>\n<p><\/p>\n<p>Questa storia \u00e8 finita qui. Passiamo alla terza storia. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/c8784e0be27883640cb8f6919a1c25e0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Anche questa \u00e8 piuttosto comune per noi, in cui eseguiamo una migrazione. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/a04b9cd88a0e7e8a3b960ef930eb2657.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Qualsiasi prodotto software cresce. I requisiti cambiano. Vogliamo svilupparci in ogni caso. E a volte \u00e8 necessario aggiornare i dati in una tabella, effettuando un aggiornamento per la nostra migrazione rispetto alla nuova funzionalit\u00e0 che stiamo introducendo nel nostro percorso di sviluppo. <\/li>\n<li>Il vecchio formato dei dati non \u00e8 soddisfacente. Supponiamo di fare riferimento alla seconda tabella, dove ho operazioni su questi conti. E supponiamo che erano in rubli, ma abbiamo deciso di aumentare la precisione e rappresentarli in copechi. E per questo dobbiamo eseguire un aggiornamento: moltiplicare il campo con l'importo dell'operazione per cento. <\/li>\n<li>Nel mondo moderno utilizziamo strumenti automatizzati per il controllo delle versioni del database. Supponiamo che <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/\">Liquibase<\/a><\/noindex>. Registriamo la nostra migrazione l\u00ec. La testiamo sul nostro database di prova. Tutto va bene. L'aggiornamento viene eseguito. Blocca l'operazione per un breve periodo, ma cos\u00ec otteniamo dati aggiornati. E possiamo attivare nuove funzionalit\u00e0 su questo. Abbiamo testato tutto, verificato. Tutto confermato. <\/li>\n<li>Abbiamo eseguito lavori pianificati e completato la migrazione. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/9e046583f7b1723fc1eaf61a03900918.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ecco la migrazione con l'aggiornamento presentata davanti a voi. Poich\u00e9 si trattava delle mie operazioni contabili, la tabella era di 15 GB. E poich\u00e9 stiamo aggiornando ogni riga, abbiamo raddoppiato la tabella, perch\u00e9 abbiamo riscritto ogni riga. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/06120c98ea43d0568045e71935c23592.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Durante la migrazione non abbiamo potuto fare nulla con questa tabella, poich\u00e9 tutte le richieste ad essa sono state messe in coda, in attesa che questo aggiornamento terminasse. Ma vorrei richiamare la vostra attenzione sui numeri sull'asse verticale. Cio\u00e8, abbiamo un tempo medio di richiesta prima della migrazione di circa 5 millisecondi e il carico della CPU, il numero di operazioni di lettura da disco \u00e8 inferiore a 7,5. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/69a3ba4d1d0cec7d39284e09e9d3055b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Abbiamo completato la migrazione e abbiamo di nuovo problemi. <\/p>\n<p><\/p>\n<p>La migrazione \u00e8 stata eseguita con successo, ma:<\/p>\n<p><\/p>\n<ul>\n<li>La funzionalit\u00e0 precedente ha iniziato a funzionare pi\u00f9 lentamente. <\/li>\n<li>La tabella \u00e8 di nuovo cresciuta in dimensioni. <\/li>\n<li>Il carico del server \u00e8 di nuovo aumentato rispetto a prima. <\/li>\n<li>E, ovviamente, stiamo ancora lavorando su quella funzionalit\u00e0 che funzionava bene, l'abbiamo migliorata un po'. <\/li>\n<\/ul>\n<p><\/p>\n<p>E questo \u00e8 di nuovo bloat, che ci crea ulteriori problemi. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/becd7cce3a1c8821c81c96257f41202b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Qui dimostro che la tabella, come nei casi precedenti, non ha intenzione di tornare alle dimensioni precedenti. Il carico medio sul server sembra essere adeguato. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/4d703a60d43a3460bc3782d49865b690.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E se guardiamo la tabella delle fatture, vediamo che il tempo medio di richiesta per quella tabella \u00e8 raddoppiato. Il carico della CPU e il numero di righe esaminate in memoria sono saltati oltre 7,5, mentre erano inferiori. E sono aumentati nel caso dei processori di 2 volte, nel caso delle operazioni di lettura di 1,5 volte, cio\u00e8 abbiamo ottenuto una degradazione delle prestazioni del server. E di conseguenza, una degradazione delle prestazioni della nostra applicazione. Anche se il numero di chiamate \u00e8 rimasto all'incirca allo stesso livello. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/80772afa0643b29f5314a2482c9dfe0d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c8 fondamentale capire come effettuare correttamente tali migrazioni. E devono essere fatte. Eseguiamo queste migrazioni piuttosto frequentemente.<\/p>\n<p><\/p>\n<ul>\n<li>Tali grandi migrazioni non vengono fatte automaticamente. Devono sempre essere sotto controllo. <\/li>\n<li>\u00c8 necessario un controllo da parte di una persona competente. Se avete un DBA nel team, lasciate che sia lui a farlo. \u00c8 il suo lavoro. Se non c'\u00e8, la persona pi\u00f9 esperta dovrebbe farlo, quella che sa come lavorare con i database. <\/li>\n<li>Una nuova struttura del database, anche se aggiorniamo solo una colonna, la prepariamo sempre in fasi, cio\u00e8 anticipatamente rispetto al rilascio della nuova versione dell'applicazione:<\/li>\n<li>Vengono aggiunti nuovi campi in cui memorizzeremo proprio i dati aggiornati. <\/li>\n<li>Trasferiamo i dati dal vecchio campo al nuovo campo in piccole porzioni. Perch\u00e9 lo facciamo? In primo luogo, controlliamo sempre il processo. Sappiamo che abbiamo trasferito gi\u00e0 un certo numero di batch e ci rimane da trasferire ancora. <\/li>\n<li>E il secondo vantaggio \u00e8 che tra ogni batch chiudiamo la transazione, ne apriamo una nuova e questo consente all'autovacuum di operare sulla tabella, contrassegnando le righe morte per il riutilizzo. <\/li>\n<li>Per le righe che appariranno durante il funzionamento dell'applicazione (abbiamo ancora l'applicazione precedente in funzione) aggiungiamo un trigger che memorizza i nuovi valori nei nuovi campi. Nel nostro caso, questo \u00e8 il vecchio valore moltiplicato per cento. <\/li>\n<li>Se siamo molto determinati e vogliamo lo stesso campo, al termine di tutte le migrazioni e prima del rilascio della nuova versione dell'applicazione, semplicemente rinominiamo i campi. I vecchi in un nome inventato, e i nuovi campi vengono rinominati in quelli vecchi. <\/li>\n<li>E solo dopo di ci\u00f2 avviamo la nuova versione dell'applicazione. <\/li>\n<\/ul>\n<p><\/p>\n<p>E in questo modo non avremo bloat e non comprometteremo le prestazioni. <\/p>\n<p><\/p>\n<p>Con questo si conclude la terza storia. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/2afab2906b5ccd30e4c8772248818057.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat.sql\">https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat.sql<\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat_approx.sql\">https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat_approx.sql<\/a><\/noindex><\/p>\n<p><\/p>\n<p>E ora parler\u00f2 pi\u00f9 in dettaglio degli strumenti che ho menzionato nella prima storia. <\/p>\n<p><\/p>\n<p>Prima di cercare il bloat, \u00e8 fondamentale installare l'estensione. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/pgstattuple.html\">pgstattuple<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Per non inventare le query, nel nostro lavoro abbiamo gi\u00e0 scritto queste query. Potete usarle. Qui sono presentate due query. <\/p>\n<p><\/p>\n<ul>\n<li>La prima funziona piuttosto a lungo, ma vi mostrer\u00e0 i valori esatti del bloat per la tabella. <\/li>\n<li>La seconda funziona pi\u00f9 rapidamente ed \u00e8 molto efficace quando bisogna valutare rapidamente se c'\u00e8 bloat o meno per la tabella. E dovete inoltre capire che il bloat nella tabella Postgres \u00e8 sempre presente. \u00c8 una caratteristica del suo modello MVCC. <\/li>\n<li>E un 20% di bloat \u00e8 normale per le tabelle nella maggior parte dei casi. Cio\u00e8, non dovete preoccuparvi e comprimere questa tabella. <\/li>\n<\/ul>\n<p><\/p>\n<p>Abbiamo capito come identificare le tabelle che sono diventate gonfie, soprattutto quando sono aumentate di dati inutili. <\/p>\n<p><\/p>\n<p>Ora parliamo di come correggere il bloat:<\/p>\n<p><\/p>\n<ul>\n<li>Se abbiamo una tabella piccola e dischi di buona qualit\u00e0, ad esempio, su una tabella fino a un gigabyte \u00e8 assolutamente possibile utilizzare VACUUM FULL. Ti prender\u00e0 un blocco esclusivo sulla tabella per alcuni secondi e sar\u00e0 tutto a posto; in cambio, eseguir\u00e0 rapidamente e in modo efficace il lavoro. Cosa fa VACUUM FULL? Si prende un blocco esclusivo sulla tabella e riscrive le righe vive da vecchi file in una nuova tabella. Alla fine, sostituisce i file vecchi con quelli nuovi. Rimuove i vecchi file e inserisce i nuovi al loro posto. Ma durante il suo lavoro, occuper\u00e0 un blocco esclusivo sulla tabella. Questo significa che non potrai fare nulla con questa tabella: n\u00e9 scrivere, n\u00e9 leggere, n\u00e9 modificarla. Inoltre, VACUUM FULL richiede spazio aggiuntivo su disco per registrare i dati.<\/li>\n<li>Il prossimo strumento <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">pg_repack<\/a><\/noindex>. Dal punto di vista del suo principio, \u00e8 molto simile a VACUUM FULL, poich\u00e9 anch'esso riscrive i dati dai vecchi file in nuovi e li sostituisce nella tabella. Tuttavia, non prende un blocco esclusivo sulla tabella all'inizio del suo lavoro, ma lo fa solo quando ha gi\u00e0 i dati pronti per sostituire i file. I requisiti di risorse del disco sono simili a quelli di VACUUM FULL. Hai bisogno di spazio aggiuntivo su disco, il che pu\u00f2 essere critico quando hai tabelle da un terabyte. \u00c8 anche piuttosto affamato di CPU, poich\u00e9 gestisce attivamente le operazioni di input\/output. <\/li>\n<li>Il terzo strumento \u00e8 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">pgcompacttable<\/a><\/noindex>. \u00c8 pi\u00f9 attento alle risorse, perch\u00e9 funziona secondo principi leggermente diversi. L'idea principale di pgcompacttable \u00e8 che utilizza gli aggiornamenti nella tabella per spostare tutte le righe vive all'inizio della tabella. Poi esegue un vacuume su questa tabella, poich\u00e9 sappiamo che all'inizio ci sono righe vive e alla fine ci sono righe morte. E il vacuum taglia gi\u00e0 questa parte finale, cio\u00e8 richiede poco spazio aggiuntivo su disco. Inoltre, pu\u00f2 essere ulteriormente ottimizzato per le risorse. <\/li>\n<\/ul>\n<p><\/p>\n<p>Con gli strumenti \u00e8 tutto. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errori comuni nelle applicazioni che portano a bloat in postgresql. Andrey Sal&#039;nikov\" src=\"\/wp-content\/uploads\/2020\/05\/4187915e54e54a0b85a342fe0280f78f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Se il tema del bloat ti sembra interessante e vuoi approfondire ulteriormente, ecco alcuni link utili:<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.slideshare.net\/alexius2Mb\/where-is-the-space-postgres\">https:\/\/www.slideshare.net\/alexius2Mb\/where-is-the-space-postgres<\/a><\/noindex> \u2013 \u00e8 una relazione del mio collega. \u00c8 generale su dove vanno a finire i dati su Postgres durante il suo funzionamento e vita. E contiene una parte tecnica molto ampia e dettagliata per gli amministratori di database sul bloat. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pg-utils\">https:\/\/github.com\/dataegret\/pg-utils<\/a><\/noindex> \u2013 \u00e8 un link al nostro repository, dove conserviamo un sacco di script utili per controllare lo stato del database. L\u00ec puoi trovare script per la ricerca del bloat. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">Terzo<\/a><\/noindex> e <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">quarta<\/a><\/noindex> link agli strumenti che ti aiuteranno a ottimizzare le tabelle. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/blog.dataegret.com\/2Mb018\/03\/postgresql-bloatbusters.html\">http:\/\/blog.dataegret.com\/2Mb018\/03\/postgresql-bloatbusters.html<\/a><\/noindex> \u2013 \u00e8 un post del mio collega. Qui analizza in modo piuttosto serio e dettagliato il bloat, a un livello molto vicino a quello degli amministratori. <\/li>\n<\/ul>\n<p><\/p>\n<p>Ho cercato di presentare uno spavento per i sviluppatori, poich\u00e9 sono i nostri principali clienti per i database e devono capire quali sono le conseguenze delle azioni intraprese. Spero di esserci riuscito. Grazie per l'attenzione!<\/p>\n<p><\/p>\n<p>Domande<\/p>\n<p><\/p>\n<p><em>Grazie per la relazione! Hai parlato di come si possono identificare i problemi. Ma come si possono prevenire? Ad esempio, ho avuto situazioni in cui le query si bloccavano non solo a causa di richieste a servizi esterni. Erano semplicemente giunzioni eccessive. C'erano piccole query inoffensive che restavano in attesa per un giorno, e poi iniziavano a causare problemi. Sembra molto simile a quanto descrivi. Come si pu\u00f2 monitorare ci\u00f2? Dobbiamo semplicemente stare a controllare quale query \u00e8 bloccata? Come si pu\u00f2 prevenire questo?<\/em><\/p>\n<p><\/p>\n<p>In questo caso, \u00e8 un compito per gli amministratori della tua azienda, non necessariamente per il DBA.<\/p>\n<p><\/p>\n<p><em>Io sono un amministratore.<\/em><\/p>\n<p><\/p>\n<p>In PostgreSQL c'\u00e8 una visualizzazione chiamata pg_stat_activity, che mostra le query bloccate. E puoi vedere per quanto tempo sono rimaste bloccate.<\/p>\n<p><\/p>\n<p><em>Devo controllare ogni 5 minuti?<\/em><\/p>\n<p><\/p>\n<p>Imposta un cron e controlla. Se si verifica una query lunga, invia una mail e basta. Quindi, non \u00e8 necessario guardare a occhio, \u00e8 possibile automatizzare. Ti arriver\u00e0 un'email e reagisci a essa. Puoi anche impostare di terminare automaticamente.<\/p>\n<p><\/p>\n<p><em>Ci sono motivi evidenti per cui ci\u00f2 accade?<\/em><\/p>\n<p><\/p>\n<p>Ne ho elencati alcuni. Altri sono esempi pi\u00f9 complessi. E la discussione potrebbe durare a lungo.<\/p>\n<p><\/p>\n<p><em>Grazie per la relazione! Volevo chiederti dell'utility pg_repack. Se non fa un blocco esclusivo, allora\u2026<\/em><\/p>\n<p><\/p>\n<p>Fa un blocco esclusivo. <\/p>\n<p><\/p>\n<p>\u2026 <em>quindi posso potenzialmente perdere dati. La mia applicazione non dovrebbe scrivere nulla in quel momento?<\/em><\/p>\n<p><\/p>\n<p>No, funziona tranquillamente con la tabella, cio\u00e8 pg_repack sposta prima tutte le righe vive. Naturalmente, ci sono dei registri nella tabella. Sta solo aggiungendo quel pezzetto alla fine. <\/p>\n<p><\/p>\n<p><em>Cio\u00e8, alla fine lo fa comunque?<\/em><\/p>\n<p><\/p>\n<p>Alla fine prende un blocco esclusivo per sostituire i file. <\/p>\n<p><\/p>\n<p><em>Sar\u00e0 pi\u00f9 veloce di VACUUM FULL?<\/em><\/p>\n<p><\/p>\n<p>VACUUM FULL, appena avviato, prende subito un blocco esclusivo. E finch\u00e9 non completa l'operazione, non lo rilascia. Mentre pg_repack prende un blocco esclusivo solo al momento della sostituzione dei file. In quel momento non puoi scrivere, ma i dati non andranno persi, tutto sar\u00e0 a posto. <\/p>\n<p><\/p>\n<p><em>Salve! Lei ha parlato del funzionamento dell'autovacuum. C'era un grafico con celle rosse, gialle e verdi. Cio\u00e8, quelle gialle sono state contrassegnate come eliminate. E di conseguenza, in esse si pu\u00f2 registrare qualcosa di nuovo?<\/em><\/p>\n<p><\/p>\n<p>S\u00ec. Postgres non elimina le righe. Ha una peculiarit\u00e0. Se aggiorniamo una riga, contrassegniamo quella vecchia come eliminata. Viene inserito l'id della transazione che ha modificato quella riga, e scriviamo una nuova riga. E abbiamo delle sessioni che potenzialmente possono leggerle. A un certo punto, queste diventano vecchie. La funzione dell'autovacuum \u00e8 quella di scorrere queste righe e contrassegnarle come non necessarie. E vi si possono riscrivere dei dati. <\/p>\n<p><\/p>\n<p><em>Ho capito. Ma la domanda \u00e8 un po' diversa. Non ho concluso. Supponiamo di avere una tabella. Ha campi di dimensioni variabili. E se provo ad inserire qualcosa di nuovo, potrebbe semplicemente non entrare nella vecchia cella.<\/em> <\/p>\n<p><\/p>\n<p>No, in ogni caso l'intera riga viene aggiornata. In Postgres ci sono due modelli di archiviazione dei dati. Viene scelto a seconda del tipo di dati. Ci sono dati che vengono memorizzati direttamente nella tabella e ci sono anche i tos-dati. Questi sono grandi volumi di dati: testo, json. Vengono memorizzati in tabelle separate. E anche per queste tabelle vale la stessa storia con il bloat, cio\u00e8 \u00e8 tutto lo stesso. Solo che sono stati isolati. <\/p>\n<p><\/p>\n<p><em>Grazie per la presentazione! Quanto \u00e8 accettabile utilizzare il timeout per le query come limite di durata?<\/em><\/p>\n<p><\/p>\n<p>\u00c8 molto accettabile. Lo usiamo ovunque. E poich\u00e9 non abbiamo i nostri servizi, ma forniamo supporto remoto, abbiamo clienti abbastanza diversi. E tutti ne sono piuttosto soddisfatti. Cio\u00e8, abbiamo compiti in cron che controllano. Si concorda con il cliente la durata delle sessioni, prima della quale non interrompiamo. Pu\u00f2 essere un minuto, possono essere 10 minuti. Dipende dal carico sul database e dal suo scopo. Ma per tutti utilizziamo pg_stat_activity.<\/p>\n<p><\/p>\n<p><em>Grazie per la presentazione! Sto cercando di adattare la tua presentazione alle mie applicazioni. E sembra che stiamo avviando la transazione ovunque, la stiamo concludendo esplicitamente in tutti i casi. Se c'\u00e8 qualche eccezione, avviene comunque il rollback. E qui mi sono chiesto. Infatti, potrebbe iniziare una transazione non esplicitamente. Questo \u00e8 un suggerimento per una ragazza, immagino. Se aggiorno semplicemente un record, la transazione inizier\u00e0 in PostgreSQL e si concluder\u00e0 solo quando avverr\u00e0 la disconnessione?<\/em><\/p>\n<p><\/p>\n<p>Se parliamo del livello dell'applicazione, dipende dal driver che stai utilizzando, dall'ORM che \u00e8 in uso. Ci sono tantissime impostazioni. Se hai attivato l'auto commit, allora la transazione inizia e si chiude immediatamente.<\/p>\n<p><\/p>\n<p><em>Cio\u00e8, si chiude subito dopo l'aggiornamento?<\/em><\/p>\n<p><\/p>\n<p>Dipende dalle impostazioni. Ho menzionato un'impostazione. \u00c8 auto commit on. \u00c8 piuttosto comune. Se \u00e8 attivata, la transazione si apre e si chiude. Se non hai esplicitamente detto 'start transaction' e 'end transaction', ma hai semplicemente avviato la query nella sessione. <\/p>\n<p><\/p>\n<p><em>Salve! Grazie per la presentazione! Immaginiamo di avere un database che continua a crescere e improvvisamente sul server finisce lo spazio. Ci sono degli strumenti per risolvere questa situazione?<\/em> <\/p>\n<p><\/p>\n<p>Lo spazio sul server dovrebbe essere monitorato bene. <\/p>\n<p><\/p>\n<p><em>Ad esempio, il DBA \u00e8 andato a prendere un t\u00e8, era in vacanza, ecc.<\/em><\/p>\n<p><\/p>\n<p>Quando viene creata una filesystem, viene riservato almeno un certo spazio addizionale dove non vengono scritti dati. <\/p>\n<p><\/p>\n<p><em>E se arriva a zero?<\/em><\/p>\n<p><\/p>\n<p>L\u00ec si chiama spazio riservato, cio\u00e8 pu\u00f2 essere liberato e a seconda di quanto grande l'hanno creato, si ottiene spazio libero. Non so quanto ci sia per default. In un altro caso, \u00e8 necessario fornire dischi, affinch\u00e9 ci sia spazio per effettuare operazioni di ripristino. Puoi eliminare qualche tabella che sai per certo non ti serve. <\/p>\n<p><\/p>\n<p><em>Non ci sono altri strumenti?<\/em><\/p>\n<p><\/p>\n<p>\u00c8 sempre lavoro manuale. E per lo spazio si determina cosa fare, perch\u00e9 ci sono dati critici e non critici. E per ogni database e per ogni applicazione che con esso lavora, dipende dal business. Si decide sempre in base allo spazio. <\/p>\n<p><\/p>\n<p><em>Grazie per la presentazione! Ho due domande. Prima di tutto, hai mostrato delle diapositive in cui era evidente che in caso di transazioni bloccate cresce sia il volume dello spazio tabellare sia la dimensione dell'indice. E poi nella presentazione c'erano un sacco di utility che impacchettano la tabella. E per quanto riguarda l'indice?<\/em><\/p>\n<p><\/p>\n<p>Anche loro vengono impacchettati. <\/p>\n<p><\/p>\n<p><em>Ma il vacuum non tocca l'indice?<\/em><\/p>\n<p><\/p>\n<p>Alcuni lavorano con gli indici. Ad esempio, pg_rapack, pgcompacttable. Il VACUUM ricrea gli indici e li tocca. La sostanza di VACUUM FULL \u00e8 riscrivere tutto, cio\u00e8 lavora con ogni indice. <\/p>\n<p><\/p>\n<p><em>E la seconda domanda. Non ho capito perch\u00e9 i report sulle repliche dipendano cos\u00ec tanto dalla replicazione stessa. Pensavo che i report fossero letture e la replicazione scritture.<\/em> <\/p>\n<p><\/p>\n<p>Dove si verifica il conflitto di replicazione? Abbiamo un Master su cui avvengono i processi. Abbiamo l'autovacuum. L'autovacuum in pratica cosa fa? Elimina alcune righe vecchie. Se in quel momento c'\u00e8 una richiesta sulla replica che legge queste righe vecchie, e sul Master \u00e8 successo che l'autovacuum ha contrassegnato queste righe come possibili per riscrittura, allora le riscriviamo. E riceviamo un pacchetto di dati quando dobbiamo riscrivere quelle righe necessarie alla richiesta sulla replica; il processo di replicazione attender\u00e0 il timeout che hai impostato. Poi PostgreSQL decider\u00e0 cosa \u00e8 pi\u00f9 importante per lui. E la replicazione \u00e8 pi\u00f9 importante della richiesta, quindi scarter\u00e0 la richiesta per eseguire queste modifiche sulla replica. <\/p>\n<p><\/p>\n<p><em>Andrey, ho una domanda. Questi grafici fantastici che hai mostrato durante la presentazione sono il risultato di un tuo strumento? Come sono stati creati i grafici?<\/em><\/p>\n<p><\/p>\n<p>\u00c8 un servizio <noindex><a rel=\"nofollow\" href=\"https:\/\/okmeter.io\/\">Okmeter<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><em>\u00c8 un prodotto commerciale?<\/em><\/p>\n<p><\/p>\n<p>S\u00ec. \u00c8 un prodotto commerciale.<\/p>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/501040\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0418 \u0432\u043e\u0437\u044c\u043c\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 Postgresql. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u044d\u0442\u043e \u043d\u0430\u0447\u0430\u043b\u043e \u043a\u043e\u043d\u0446\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":81090,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-81089","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql. \u0410\u043d\u0434\u0440\u0435\u0439 \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-05-10T23:42:24+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-05-10T23:42:24+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Errori tipici nelle applicazioni che portano a bloat in PostgreSQL. Andrey Salnikov | ProHoster","description":"Vi invitiamo a leggere la trascrizione della relazione di inizio 2016 di Andrey Sal'nikov \"Errori tipici nelle applicazioni che portano a bloat in postgresql\". In questa relazione esaminer\u00f2 i punti principali.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql. \u0410\u043d\u0434\u0440\u0435\u0439 \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432 | ProHoster","og:description":"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435.","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-05-10T23:42:24+00:00","article:modified_time":"2020-05-10T23:42:24+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"81089","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:05:22","updated":"2022-09-27 16:01:50","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/81089","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=81089"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/81089\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/81090"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=81089"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=81089"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=81089"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}