{"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\/es\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","title":{"rendered":"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>Te invito a revisar la transcripci\u00f3n de la conferencia de principios de 2016 de Andrei Salnikov \"Errores t\u00edpicos en aplicaciones que conducen al bloat en PostgreSQL\"<\/strong><\/p>\n<p><\/p>\n<p>En este informe, analizar\u00e9 los errores principales en las aplicaciones que surgen en la etapa de dise\u00f1o y escritura del c\u00f3digo de la aplicaci\u00f3n. Me centrar\u00e9 solo en aquellos errores que conducen al bloat en PostgreSQL. Por lo general, esto marca el inicio del fin del rendimiento de su sistema en general, aunque inicialmente no se ve\u00edan se\u00f1ales de ello.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" 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>\u00a1Saludos a todos! Este informe no es tan t\u00e9cnico como el anterior de mi colega. Est\u00e1 orientado principalmente a desarrolladores de sistemas backend, porque tenemos una cantidad considerable de clientes. Y todos cometen los mismos errores. De eso les hablar\u00e9. Explicar\u00e9 las consecuencias fatales y negativas de estos errores. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/c6c84dbafc595ae3068cd8bf804ccee7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfPor qu\u00e9 se cometen errores? Se cometen por dos razones: por casualidad, pensando que puede funcionar, y por desconocimiento de ciertos mecanismos que ocurren a nivel entre la base de datos y la aplicaci\u00f3n, as\u00ed como dentro de la propia base de datos. <\/p>\n<p><\/p>\n<p>Les dar\u00e9 tres ejemplos con im\u00e1genes horribles de c\u00f3mo todo se ha vuelto malo. Resumir\u00e9 el mecanismo que ocurre all\u00ed. Y c\u00f3mo combatirlos cuando ocurren, as\u00ed como qu\u00e9 m\u00e9todos preventivos utilizar para evitar errores. Hablaremos de herramientas auxiliares y proporcionar\u00e9 enlaces \u00fatiles. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/b0230d992f5b44f0e542df2e4b4d526f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Utilic\u00e9 una base de datos de prueba, donde ten\u00eda dos tablas. Una tabla con las cuentas de los clientes, y la otra con las operaciones en estas cuentas. Y con cierta periodicidad, actualizamos los saldos en estas cuentas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/1d2a21278b095b07546e1bb870819dbf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Los datos de origen de la tabla: es bastante peque\u00f1a, 2 MB. El tiempo de respuesta de la base de datos y espec\u00edficamente de la tabla tambi\u00e9n es muy bueno. Y la carga es suficientemente buena: 2,000 operaciones por segundo en la tabla.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/dea5a4b1ac7952f8cfed0e2e1cfc10dd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y a lo largo de este informe, les mostrar\u00e9 gr\u00e1ficos para que sea evidente lo que est\u00e1 sucediendo. Siempre habr\u00e1 2 diapositivas con gr\u00e1ficos. La primera diapositiva mostrar\u00e1 lo que ocurre en el servidor en general. <\/p>\n<p><\/p>\n<p>Y en esta situaci\u00f3n, vemos que de hecho, tenemos una tabla de tama\u00f1o peque\u00f1o. Un \u00edndice peque\u00f1o de 2 MB. Este es el primer gr\u00e1fico a la izquierda. <\/p>\n<p><\/p>\n<p>El tiempo medio de respuesta del servidor tambi\u00e9n es estable y bajo. Este es el gr\u00e1fico superior derecho. <\/p>\n<p><\/p>\n<p>El gr\u00e1fico inferior izquierdo muestra las transacciones m\u00e1s prolongadas. Vemos que las transacciones se completan r\u00e1pidamente. Y el autovacuum a\u00fan no est\u00e1 funcionando aqu\u00ed, porque fue una prueba inicial. M\u00e1s adelante funcionar\u00e1 y ser\u00e1 \u00fatil para nosotros.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/9e9b46acd9a878ff70ca4a7850adff09.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>La segunda diapositiva siempre se dedicar\u00e1 a la tabla en prueba. En esta situaci\u00f3n, actualizamos constantemente los saldos de las cuentas del cliente. Y vemos que el tiempo de respuesta promedio para la operaci\u00f3n de actualizaci\u00f3n es bastante bueno, menos de una mil\u00e9sima de segundo. Vemos que los recursos de la CPU (esto es el gr\u00e1fico superior derecho) se consumen de manera uniforme y en cantidades bastante peque\u00f1as. <\/p>\n<p><\/p>\n<p>El gr\u00e1fico inferior derecho muestra cu\u00e1nto de memoria operativa y de disco estamos recorriendo en busca de nuestra l\u00ednea necesaria antes de actualizarla. Y la cantidad de operaciones en la tabla es de 2,000 por segundo, como mencion\u00e9 al principio. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/84760d52716209b8dcfffb462c67a8e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y ahora ocurre una tragedia. Por alguna raz\u00f3n, aparece una transacci\u00f3n olvidada y prolongada. Las razones suelen ser bastante banales: <\/p>\n<p><\/p>\n<ul>\n<li>Una de las m\u00e1s comunes es que en el c\u00f3digo de la aplicaci\u00f3n comenzamos a comunicarnos con un servicio externo. Y ese servicio no nos responde. Es decir, abrimos una transacci\u00f3n, hicimos un cambio en la base de datos y nos fuimos a leer correos o a otro servicio dentro de nuestra infraestructura, y por alguna raz\u00f3n no nos responde. Y nuestra sesi\u00f3n queda colapsada en un estado \u2013 no se sabe cu\u00e1ndo se resolver\u00e1.<\/li>\n<li>La segunda situaci\u00f3n ocurre cuando en nuestro c\u00f3digo, por alguna raz\u00f3n, se produce una excepci\u00f3n. Y no procesamos el cierre de la transacci\u00f3n en la excepci\u00f3n. Y terminamos con una sesi\u00f3n colgada con una transacci\u00f3n abierta. <\/li>\n<li>Y, finalmente, este tambi\u00e9n es un caso bastante com\u00fan. Es c\u00f3digo de mala calidad. Algunos frameworks abren una transacci\u00f3n. Esta queda suspendida, y es posible que no sepas en la aplicaci\u00f3n que est\u00e1 as\u00ed. <\/li>\n<\/ul>\n<p><\/p>\n<p>\u00bfA qu\u00e9 conducen estas cosas? <\/p>\n<p><\/p>\n<p>A que nuestras tablas e \u00edndices comienzan a hincharse dr\u00e1sticamente. Este es precisamente el efecto bloat. Para la base de datos, esto se expresar\u00e1 en un aumento brusco en el tiempo de respuesta de la base de datos, y aumentar\u00e1 la carga en el servidor de la base de datos. Como resultado, nuestra aplicaci\u00f3n sufrir\u00e1. Porque si en el c\u00f3digo dedicas 10 milisegundos a una consulta de la base de datos, 10 milisegundos a tu l\u00f3gica, entonces tu funci\u00f3n funcionaba en 20 milisegundos. Pero ahora la situaci\u00f3n ser\u00e1 bastante triste. <\/p>\n<p><\/p>\n<p>Y veamos qu\u00e9 est\u00e1 pasando. El gr\u00e1fico inferior izquierdo muestra que tenemos una transacci\u00f3n prolongada. Y si miramos el gr\u00e1fico superior izquierdo, vemos que el tama\u00f1o de la tabla ha saltado abruptamente de dos megabytes a 300 megabytes. Sin embargo, la cantidad de datos en la tabla no ha cambiado, es decir, hay una gran cantidad de basura.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/b1947f6487e440a770a1251a955e62d2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>La situaci\u00f3n general en cuanto al tiempo medio de respuesta del servidor tambi\u00e9n ha cambiado dr\u00e1sticamente. Es decir, todas las solicitudes al servidor han comenzado a caer considerablemente. Adem\u00e1s, se han iniciado los procesos internos de Postgres en forma de autovacuum, que intentan hacer algo y consumen recursos.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/8e91f035d1dd04e72e842d714cc611a5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfQu\u00e9 est\u00e1 ocurriendo con nuestra tabla? Lo mismo. El tiempo medio de respuesta de la tabla ha aumentado dr\u00e1sticamente. En cuanto a los recursos consumidos, vemos que la carga en el procesador ha aumentado significativamente. Este es el gr\u00e1fico superior derecho. Y ha aumentado porque el procesador tiene que revisar muchas filas innecesarias en busca de una necesaria. Este es el gr\u00e1fico inferior derecho. Y como resultado, el n\u00famero de llamadas por segundo ha comenzado a caer significativamente, porque la base no puede procesar la misma cantidad de solicitudes. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/424685ce852bc5f3ef77151f8d3d7289.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Necesitamos volver a la vida. Vamos a internet y descubrimos que las transacciones largas causan problemas. Encontramos y eliminamos esa transacci\u00f3n. Y todo vuelve a estar normal. Todo funciona como deber\u00eda. <\/p>\n<p><\/p>\n<p>Nos calmamos, pero despu\u00e9s de un tiempo comenzamos a notar que la aplicaci\u00f3n no funciona como antes de la situaci\u00f3n de emergencia. Las solicitudes siguen siendo procesadas m\u00e1s lento, y significativamente m\u00e1s lento. En mi caso, una vez y media a dos veces m\u00e1s lento. La carga en el servidor tambi\u00e9n es superior a la que hab\u00eda antes de la emergencia. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/ee3037719a31f8d18fc42745716c4da5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y la pregunta es: \"\u00bfQu\u00e9 est\u00e1 pasando con la base en este momento?\". Con la base est\u00e1 ocurriendo la siguiente situaci\u00f3n. En el gr\u00e1fico de transacciones, ves que se ha detenido y realmente no hay transacciones largas. Pero los tama\u00f1os de la tabla durante la emergencia han aumentado fatalmente. Y desde entonces no han disminuido. El tiempo medio en la base se ha estabilizado. Y las respuestas parecen estar fluyendo de manera adecuada a una velocidad aceptable para nosotros. El autovacuum se ha vuelto m\u00e1s activo y ha comenzado a hacer algo con la tabla, porque necesita procesar una mayor cantidad de datos. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/f6205242c4024dc3ed4cade5844dbf76.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Espec\u00edficamente sobre la tabla de cuentas en la que cambiamos los saldos: el tiempo de respuesta a la consulta parece haber vuelto a la normalidad. Pero en realidad, es una vez y media m\u00e1s alto.<\/p>\n<p><\/p>\n<p>Y respecto a la carga del procesador, vemos que no ha regresado a los niveles requeridos antes de la falla. Las causas se encuentran en el gr\u00e1fico de la esquina inferior derecha. Es evidente que estamos sobresaturando una cierta cantidad de memoria. Es decir, para encontrar la l\u00ednea necesaria, estamos gastando recursos del servidor de bases de datos al procesar datos in\u00fatiles. La cantidad de transacciones por segundo se ha estabilizado. <\/p>\n<p><\/p>\n<p>En general, est\u00e1 bien, pero la situaci\u00f3n es peor que antes. Hay una clara degradaci\u00f3n de la base de datos como consecuencia de nuestra aplicaci\u00f3n que trabaja con esta base de datos. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/0dfc9cd453fd84bc639ffd99cf189fd2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y para entender qu\u00e9 est\u00e1 sucediendo, si no asistieron a la presentaci\u00f3n anterior, ahora un poco de teor\u00eda. Teor\u00eda sobre el proceso interno. \u00bfPara qu\u00e9 sirve el autovacuum y qu\u00e9 hace?<\/p>\n<p><\/p>\n<p>Brevemente, para la comprensi\u00f3n. En alg\u00fan momento, tenemos una tabla. En la tabla hay filas. Estas filas pueden ser activas, vivas, que necesitamos ahora. En la imagen, est\u00e1n marcadas en verde. Y hay filas muertas, que ya han sido procesadas, actualizadas, y aparecen nuevos registros sobre ellas. Y est\u00e1n marcadas como que ya no interesan a la base de datos. Pero permanecen en la tabla debido a las peculiaridades de Postgres.<\/p>\n<p><\/p>\n<p>\u00bfPara qu\u00e9 se necesita el autovacuum? El autovacuum en alg\u00fan momento se presenta, se dirige a la base de datos y le pregunta: \"Dame, por favor, el id de la transacci\u00f3n m\u00e1s antigua que est\u00e1 abierta en este momento en la base de datos\". La base de datos devuelve este id. Y el autovacuum, bas\u00e1ndose en \u00e9l, revisa las filas de la tabla. Si ve que algunas filas han sido modificadas por transacciones mucho m\u00e1s antiguas, entonces tiene derecho a marcarlas como filas que podemos reutilizar en el futuro, escribiendo nuevos datos en ellas. Este es un proceso en segundo plano.<\/p>\n<p><\/p>\n<p>Mientras tanto, seguimos trabajando con la base de datos, seguimos realizando algunos cambios en la tabla. Y sobre estas filas que podemos reutilizar, escribimos nuevos datos. De esta manera, tenemos un ciclo, es decir, constantemente aparecen en la base de datos algunas filas muertas antiguas, y en su lugar escribimos nuevas filas que necesitamos. Y este es un estado normal para el funcionamiento de PostgreSQL.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/98dd4451a7ca5f418775f72822c2840c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfQu\u00e9 sucedi\u00f3 durante el accidente? \u00bfC\u00f3mo se desarroll\u00f3 este proceso?<\/p>\n<p><\/p>\n<p>Ten\u00edamos una tabla en alg\u00fan estado, algunas filas vivas y otras muertas. Vino el autovacuum. Pregunt\u00f3 a la base de datos cu\u00e1l era nuestra transacci\u00f3n m\u00e1s antigua y cu\u00e1l era su id. Obtuvo este id, que podr\u00eda tener horas de antig\u00fcedad o solo diez minutos. Esto depende de cu\u00e1n alta sea la carga en su base de datos. Y comenz\u00f3 a buscar filas que pudiera marcar como reutilizables. Y no encontr\u00f3 tales filas en nuestra tabla. <\/p>\n<p><\/p>\n<p>Pero mientras tanto seguimos trabajando en la tabla. Hacemos algo en ella, actualizamos, cambiamos datos. \u00bfY qu\u00e9 debe hacer la base de datos en ese momento? No le queda otra opci\u00f3n que a\u00f1adir nuevas filas al final de la tabla existente. De esta manera, el tama\u00f1o de la tabla comienza a aumentar. <\/p>\n<p><\/p>\n<p>Realmente necesitamos filas verdes para trabajar. Pero durante un problema as\u00ed, el porcentaje de filas verdes en toda la tabla es extremadamente bajo. <\/p>\n<p><\/p>\n<p>Y cuando ejecutamos una consulta, la base de datos tiene que recorrer todas las filas: tanto las rojas como las verdes, para encontrar la fila correcta. Y el efecto de inflaci\u00f3n de la tabla con datos innecesarios se llama \"bloat\", que tambi\u00e9n consume nuestro espacio en disco. \u00bfRecuerdas, ten\u00eda 2 MB, ahora tiene 300 MB? Ahora cambia megabytes por gigabytes y r\u00e1pidamente te quedar\u00e1s sin espacio en tus recursos de disco.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/fe7cb6b5c99610744ebcfe5ad7235d1e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfQu\u00e9 consecuencias pueden haber para nosotros? <\/p>\n<p><\/p>\n<ul>\n<li>En mi ejemplo, la tabla y el \u00edndice crecieron 150 veces. Algunos de nuestros clientes han tenido casos m\u00e1s fatales, donde simplemente se empezaba a acabar el espacio en disco. <\/li>\n<li>El tama\u00f1o de las tablas por s\u00ed mismo nunca disminuir\u00e1. El autovacuum en algunos casos puede recortar la cola de la tabla si solo hay filas muertas. Pero dado que hay una rotaci\u00f3n constante, una fila verde puede quedarse al final y no actualizarse, mientras que todas las dem\u00e1s se registran en la parte superior de la tabla. Pero esto es un evento tan poco probable que no debemos esperar que nuestra tabla disminuya de tama\u00f1o por s\u00ed sola. <\/li>\n<li>La base de datos necesita revisar toda una pila de filas in\u00fatiles. Y estamos gastando recursos de disco, recursos de procesador y electricidad. <\/li>\n<li>Y esto afecta directamente a nuestra aplicaci\u00f3n, porque si al principio gast\u00e1bamos 10 milisegundos en la solicitud, 10 milisegundos en nuestro c\u00f3digo, durante la ca\u00edda comenzamos a gastar un segundo en la solicitud y 10 milisegundos en el c\u00f3digo, es decir, el rendimiento de la aplicaci\u00f3n disminuy\u00f3 en un orden de magnitud. Y cuando se resolvi\u00f3 la ca\u00edda, comenzamos a gastar 20 milisegundos en la solicitud, 10 milisegundos en el c\u00f3digo. Esto significa que a\u00fan as\u00ed ca\u00edmos en un 50% en rendimiento. Y todo esto debido a una transacci\u00f3n que qued\u00f3 atascada, posiblemente por nuestra culpa. <\/li>\n<li>Y la pregunta es: \u00ab\u00bfC\u00f3mo lo revertimos?\u00bb, para que todo funcione bien y las solicitudes corran tan r\u00e1pido como antes de la ca\u00edda. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/1bf46e8cd9b28ca2862f978f2ca85819.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Para ello, hay un ciclo de trabajo espec\u00edfico que se lleva a cabo. <\/p>\n<p><\/p>\n<p>Primero necesitamos encontrar las tablas problem\u00e1ticas que se han expandido. Entendemos que para algunas tablas la escritura es m\u00e1s activa, para otras menos activa. Y para esto se utiliza la extensi\u00f3n <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/pgstattuple.html\">pgstattuple<\/a><\/noindex>. Al instalar esta extensi\u00f3n, puedes escribir consultas que te ayudar\u00e1n a encontrar las tablas que han crecido significativamente. <\/p>\n<p><\/p>\n<p>Despu\u00e9s de encontrar estas tablas, es necesario comprimirlas. Para ello, ya hay herramientas. En nuestra empresa usamos tres herramientas. La primera es VACUUM FULL integrado. Es duro, severo y despiadado, pero a veces es muy \u00fatil. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">Pg_repack<\/a><\/noindex> y <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">pgcompacttable<\/a><\/noindex> son utilidades externas para comprimir tablas. Y son m\u00e1s cuidadosas con la base de datos. <\/p>\n<p><\/p>\n<p>Se utilizan dependiendo de lo que te resulte m\u00e1s conveniente. Pero de esto hablar\u00e9 al final. Lo principal es que hay tres herramientas. Hay de d\u00f3nde elegir. <\/p>\n<p><\/p>\n<p>Despu\u00e9s de que hayamos hecho todas las correcciones y nos hayamos asegurado de que todo est\u00e9 bien, debemos saber c\u00f3mo prevenir esta situaci\u00f3n en el futuro:<\/p>\n<p><\/p>\n<ul>\n<li>Se previene bastante f\u00e1cil. Es necesario monitorear la duraci\u00f3n de las sesiones en el servidor maestro. <strong>Las sesiones especialmente peligrosas est\u00e1n en estado de idle in transaction<\/strong>. Son aquellas que abrieron una transacci\u00f3n, hicieron algo y se fueron o simplemente se quedaron atrapadas, perdidas en el c\u00f3digo. <\/li>\n<li>Y para ustedes, como desarrolladores, es importante probar el c\u00f3digo en el momento en que se presentan estas situaciones. No es dif\u00edcil hacerlo. Ser\u00e1 una revisi\u00f3n \u00fatil. Evitar\u00e1n una gran cantidad de problemas 'infantiles' relacionados con transacciones prolongadas. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/d55465d96c4018db733954867d23aaba.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En estos gr\u00e1ficos, quer\u00eda mostrarles c\u00f3mo cambi\u00f3 la tabla y el comportamiento de la base de datos despu\u00e9s de que pas\u00e9 por la tabla con VACUUM FULL. Esto no est\u00e1 en producci\u00f3n.<\/p>\n<p><\/p>\n<p>El tama\u00f1o de la tabla volvi\u00f3 a un estado operativo normal de unos pocos megabytes. Esto no afect\u00f3 significativamente el tiempo de respuesta del servidor. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/cbb07ad24dba899395223d1ca25e438e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pero en nuestra tabla de prueba, donde actualizamos los saldos en las cuentas, vemos que el tiempo medio de respuesta para la actualizaci\u00f3n de datos en la tabla se redujo a un nivel previo a la crisis. Los recursos consumidos por el procesador para ejecutar esta consulta tambi\u00e9n cayeron a niveles anteriores a la crisis. Y el gr\u00e1fico en la esquina inferior derecha muestra que ahora encontramos exactamente la fila que necesitamos de inmediato, sin tener que revisar un mont\u00f3n de filas muertas que exist\u00edan antes de la compresi\u00f3n de la tabla. El tiempo medio de las consultas se mantiene aproximadamente al mismo nivel. Pero aqu\u00ed, m\u00e1s bien, tengo un margen de error de mi hardware.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/c1d90c5442e02fce209dc40e048a8ca2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aqu\u00ed termina la primera historia. Es la m\u00e1s com\u00fan y le sucede a todos, independientemente de la experiencia del cliente o de cu\u00e1n calificados sean los programadores. Tarde o temprano esto sucede. <\/p>\n<p><\/p>\n<p>La segunda historia, en la que distribuimos la carga y optimizamos los recursos del servidor.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/cda421c554d1329107ddc935045cc1b9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Ya hemos crecido y nos hemos convertido en una empresa seria. Y sabemos que tenemos una r\u00e9plica y ser\u00eda bueno equilibrar la carga: escribir en el Maestro y leer de la r\u00e9plica. Y generalmente esta situaci\u00f3n surge cuando queremos generar informes o realizar ETL. Y el negocio est\u00e1 muy contento con esto. Quiere informes variados con un mont\u00f3n de an\u00e1lisis complejos. <\/li>\n<li>Los informes llevan horas porque no se puede calcular un an\u00e1lisis complejo en milisegundos. Nosotros, como chicos valientes, escribimos c\u00f3digo. Hacemos inserciones en la aplicaci\u00f3n, escribimos en el Maestro y ejecutamos los informes en la r\u00e9plica. <\/li>\n<li>Distribuimos la carga. <\/li>\n<li>Todo funciona perfectamente. Somos geniales. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/e94c8c492197a5015ac8aae79389a4c2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfY c\u00f3mo se ve esta situaci\u00f3n? En estos gr\u00e1ficos, tambi\u00e9n a\u00f1ad\u00ed la duraci\u00f3n de las transacciones desde la r\u00e9plica para la duraci\u00f3n de la transacci\u00f3n. Todos los dem\u00e1s gr\u00e1ficos se refieren solo al servidor Maestro. <\/p>\n<p><\/p>\n<p>La tabla de informes ha crecido hasta este momento. Hay m\u00e1s informes. Vemos que el tiempo medio de respuesta del servidor es estable. Notamos que hay una transacci\u00f3n larga en la r\u00e9plica que lleva 2 horas. Vemos el funcionamiento tranquilo del autovacuum que est\u00e1 procesando las filas muertas. Y todo va bien. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/2da8acf098d12d6f146ab9b9dcb54b81.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Espec\u00edficamente en la tabla en cuesti\u00f3n, seguimos actualizando los saldos en las cuentas. Tambi\u00e9n tenemos un tiempo de respuesta estable para las consultas, un consumo de recursos estable. Todo va bien. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/3621ef723017bac6fb635caf0a5f4de6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Todo va bien hasta que los informes comienzan a fallar debido a un conflicto con la replicaci\u00f3n. Y estos fallos ocurren de forma continua. <\/p>\n<p><\/p>\n<p>Nos metemos en Internet y empezamos a leer por qu\u00e9 est\u00e1 sucediendo esto. Y encontramos una soluci\u00f3n. <\/p>\n<p><\/p>\n<p>La primera soluci\u00f3n es aumentar el retraso de replicaci\u00f3n. Sabemos que nuestro informe tarda 3 horas en procesarse. Establecemos el retraso de replicaci\u00f3n a 3 horas. Ejecutamos todo, pero a\u00fan continuamos teniendo problemas con los informes que a veces fallan. <\/p>\n<p><\/p>\n<p>Queremos que todo funcione perfectamente. Buscamos m\u00e1s y encontramos una buena configuraci\u00f3n en Internet: hot_standby_feedback. Lo activamos. Hot_standby_feedback nos permite retener el funcionamiento del autovacuum en el maestro. De este modo, eliminamos por completo los conflictos de replicaci\u00f3n. Y todo funciona bien con los informes.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/ee3c315168bdd3f392d2e8a1c5861004.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfY qu\u00e9 est\u00e1 sucediendo con el servidor maestro en este momento? La situaci\u00f3n en el servidor maestro es cr\u00edtica. Ahora estamos observando los gr\u00e1ficos desde que activ\u00e9 estas dos configuraciones. Y vemos que las sesiones en la r\u00e9plica de alguna manera han empezado a influir en la situaci\u00f3n del servidor maestro. De hecho, est\u00e1n influyendo, ya que han detenido el autovacuum que limpia las filas muertas. El tama\u00f1o de la tabla ha vuelto a dispararse. El tiempo medio de ejecuci\u00f3n de las consultas en toda la base de datos tambi\u00e9n ha aumentado considerablemente. Los autovacuums se han tensado un poco. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/980611dcce8b189dc50f422ffd3d2d72.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Concretamente en nuestra tabla, vemos que la actualizaci\u00f3n de datos tambi\u00e9n ha aumentado considerablemente. El consumo de recursos de la CPU tambi\u00e9n ha aumentado dr\u00e1sticamente. Nuevamente estamos procesando una gran cantidad de filas muertas e in\u00fatiles. Y el tiempo de respuesta para esta tabla y el n\u00famero de transacciones han ca\u00eddo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/a648fd313a5dccf45f0056dc13c54263.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfC\u00f3mo se ver\u00eda esto si no supi\u00e9ramos de qu\u00e9 estaba hablando antes?<\/p>\n<p><\/p>\n<ul>\n<li>Comenzamos a buscar problemas. Si hemos enfrentado problemas en la primera parte, sabemos que la causa puede ser una transacci\u00f3n larga y vamos al Maestro. El problema est\u00e1 en el Maestro. Est\u00e1 fallando. Se calienta, su carga promedio est\u00e1 cerca del cien. <\/li>\n<li>Las solicitudes est\u00e1n desaceleradas all\u00ed, pero no vemos transacciones largas. Y no entendemos qu\u00e9 est\u00e1 pasando. No sabemos d\u00f3nde buscar. <\/li>\n<li>Verificamos el hardware del servidor. Puede que se haya estropeado el RAID. Puede que se haya quemado un m\u00f3dulo de memoria. Cualquier cosa puede suceder. Pero no, los servidores son nuevos, todo funciona perfectamente. <\/li>\n<li>Todos est\u00e1n corriendo: administradores, desarrolladores y el director. Nada ayuda. <\/li>\n<li>Y en alg\u00fan momento, de repente, todo comienza a corregirse solo. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/7d4f6417bc5cb3cec33679d843c6661d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mientras tanto, en la r\u00e9plica, una solicitud se proces\u00f3 y se fue. Recibimos el informe. El negocio sigue satisfecho. Como podemos ver, la tabla ha crecido nuevamente y no parece que vaya a disminuir. En el gr\u00e1fico de sesiones dej\u00e9 una parte de esta larga transacci\u00f3n de la r\u00e9plica para que puedan evaluar cu\u00e1nto tiempo pasa hasta que la situaci\u00f3n se estabiliza. <\/p>\n<p><\/p>\n<p>La sesi\u00f3n se fue. Y solo despu\u00e9s de un tiempo, el servidor vuelve m\u00e1s o menos a la normalidad. Y el tiempo medio de respuesta de las solicitudes en el servidor Maestro se normaliza. Porque, finalmente, el autovacuum tuvo la oportunidad de limpiar, marcar esas l\u00edneas muertas. Y comenz\u00f3 a hacer su trabajo. Y tan r\u00e1pido como lo hace, as\u00ed de r\u00e1pido volveremos a la normalidad.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/547d195e08de1566da818150a47218eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En la tabla de prueba, donde actualizamos los saldos de las cuentas, vemos un patr\u00f3n muy similar. El tiempo medio de actualizaci\u00f3n de cuentas tambi\u00e9n se normaliza gradualmente. Los recursos consumidos por la CPU tambi\u00e9n disminuyen. Y la cantidad de transacciones por segundo vuelve a la normalidad. Pero nuevamente a una normalidad que no es la que ten\u00edamos antes del accidente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/29372a5e9124690931485a7aea65befc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>De todos modos, experimentamos una ca\u00edda en el rendimiento como en el primer caso de una vez y media a dos veces, o a veces incluso m\u00e1s. <\/p>\n<p><\/p>\n<p>Parece que hicimos todo correctamente. Distribuimos la carga. El hardware no est\u00e1 inactivo. Desglosamos las solicitudes de manera inteligente, pero de todos modos, todo sali\u00f3 mal. <\/p>\n<p><\/p>\n<ul>\n<li>\u00bfNo activar hot_standby_feedback? S\u00ed, no se recomienda activarlo sin razones de peso. Porque este ajuste afecta directamente al Servidor Maestro y detiene el funcionamiento del autovacuum all\u00ed. Si lo activas en alguna r\u00e9plica y olvidas sobre esto, puedes perjudicar al Maestro y tener problemas importantes con la aplicaci\u00f3n. <\/li>\n<li>\u00bfAumentar max_standby_streaming_delay? S\u00ed, para los informes \u2013 as\u00ed es. Si tienes un informe de tres horas y no quieres que se caiga debido a conflictos de replicaci\u00f3n, simplemente aumenta el retraso. Un informe prolongado nunca requiere datos que hayan llegado a la base en este momento. Si es de tres horas, significa que lo est\u00e1s ejecutando para un per\u00edodo de datos antiguo. Y para ti, tres horas de retraso o seis horas no marcar\u00e1n diferencia, pero as\u00ed recibir\u00e1s informes de manera estable y no tendr\u00e1s problemas con su ca\u00edda. <\/li>\n<li>Naturalmente, es necesario controlar las sesiones largas en las r\u00e9plicas, especialmente si has decidido activar hot_standby_feedback en la r\u00e9plica. Porque puede pasar cualquier cosa. Se le dio esta r\u00e9plica a un desarrollador para que probara las consultas. \u00c9l escribi\u00f3 una consulta loca. La ejecut\u00f3 y se fue a tomar t\u00e9, y nosotros obtenemos un Maestro complicado. O introdujimos la aplicaci\u00f3n incorrecta. Las situaciones son variadas. Las sesiones en las r\u00e9plicas deben controlarse con tanto cuidado como en el Maestro. <\/li>\n<li>Y si tienes consultas r\u00e1pidas y prolongadas en las r\u00e9plicas, en este caso es mejor dividirlas para distribuir la carga. Este es un enlace al streaming_delay. Para las r\u00e1pidas, tener una r\u00e9plica con un peque\u00f1o retraso en la replicaci\u00f3n. Para las consultas prolongadas, tener una r\u00e9plica que pueda retrasarse entre 6 horas y un d\u00eda. Esta es una situaci\u00f3n bastante normal. <\/li>\n<\/ul>\n<p><\/p>\n<p>Eliminamos las consecuencias de la misma manera:<\/p>\n<p><\/p>\n<ul>\n<li>Encontramos las tablas infladas.<\/li>\n<li>Y comprimimos con la herramienta m\u00e1s adecuada para nosotros. <\/li>\n<\/ul>\n<p><\/p>\n<p>La segunda historia termina aqu\u00ed. Pasamos a la tercera historia. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/c8784e0be27883640cb8f6919a1c25e0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tambi\u00e9n es bastante com\u00fan para nosotros, en la que hacemos una migraci\u00f3n. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/a04b9cd88a0e7e8a3b960ef930eb2657.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Cualquier producto de software crece. Cambian los requisitos. De todas formas, queremos desarrollarnos. Y a veces necesitamos actualizar los datos en la tabla, espec\u00edficamente ejecutar la actualizaci\u00f3n en el marco de nuestra migraci\u00f3n hacia la nueva funcionalidad que implementamos en el contexto de nuestro desarrollo. <\/li>\n<li>El formato de datos antiguo no es adecuado. Supongamos que ahora nos dirigimos a la segunda tabla, donde tengo operaciones en estas cuentas. Y, supongamos que estaban en rublos, y decidimos aumentar la precisi\u00f3n y trabajar en kopeks. Para ello, necesitamos hacer una actualizaci\u00f3n: multiplicar el campo con el monto de la operaci\u00f3n por cien. <\/li>\n<li>En el mundo moderno, utilizamos herramientas automatizadas para el control de versiones de bases de datos. Supongamos, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/\">Liquibase<\/a><\/noindex>. Escribimos nuestra migraci\u00f3n all\u00ed. La probamos en nuestra base de datos de prueba. Todo est\u00e1 excelente. La actualizaci\u00f3n se lleva a cabo. Bloquea el trabajo durante un tiempo, pero obtenemos datos actualizados. Y podemos lanzar nueva funcionalidad basada en esto. Todo ha sido probado y verificado. Todo est\u00e1 confirmado. <\/li>\n<li>Se realizaron trabajos planificados, se llev\u00f3 a cabo la migraci\u00f3n. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/9e046583f7b1723fc1eaf61a03900918.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aqu\u00ed se presenta la migraci\u00f3n con la actualizaci\u00f3n. Dado que se trata de operaciones en cuentas, la tabla ten\u00eda 15 GB. Y como estamos actualizando cada fila, la actualizaci\u00f3n duplic\u00f3 el tama\u00f1o de la tabla porque reescribimos cada fila. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/06120c98ea43d0568045e71935c23592.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Durante la migraci\u00f3n no pudimos hacer nada con esta tabla, porque todas las consultas a ella se pusieron en cola y esperaron a que finalizara esta actualizaci\u00f3n. Pero aqu\u00ed quiero llamar su atenci\u00f3n sobre los n\u00fameros en el eje vertical. Es decir, tenemos un tiempo medio de consulta antes de la migraci\u00f3n de alrededor de 5 milisegundos y una carga en el procesador, el n\u00famero de operaciones de bloque para la lectura de la memoria del disco es menor que en 7.5. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/69a3ba4d1d0cec7d39284e09e9d3055b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Realizamos la migraci\u00f3n y nuevamente tuvimos problemas. <\/p>\n<p><\/p>\n<p>La migraci\u00f3n fue exitosa, pero:<\/p>\n<p><\/p>\n<ul>\n<li>La funcionalidad antigua comenz\u00f3 a tardar m\u00e1s en ejecutarse. <\/li>\n<li>La tabla nuevamente aument\u00f3 de tama\u00f1o. <\/li>\n<li>La carga en el servidor nuevamente se volvi\u00f3 mayor que antes. <\/li>\n<li>Y, por supuesto, mientras seguimos trabajando con la funcionalidad que funcionaba bien, la mejoramos un poco. <\/li>\n<\/ul>\n<p><\/p>\n<p>Y esto es nuevamente un bloat que nos arruina la vida una vez m\u00e1s. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/becd7cce3a1c8821c81c96257f41202b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aqu\u00ed demuestro que la tabla, al igual que en los dos casos anteriores, no tiene intenci\u00f3n de volver a sus tama\u00f1os anteriores. La carga promedio del servidor parece ser adecuada. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/4d703a60d43a3460bc3782d49865b690.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Si consultamos la tabla de cuentas, veremos que el tiempo medio de consulta se ha duplicado con respecto a esta tabla. La carga en el procesador y la cantidad de filas procesadas en memoria ha superado 7.5, mientras que antes estaba por debajo. Adem\u00e1s, en el caso de los procesadores, ha aumentado el doble, y en las operaciones por lotes, 1.5 veces, es decir, hemos experimentado una degradaci\u00f3n del rendimiento del servidor. Y, como consecuencia, una degradaci\u00f3n del rendimiento de nuestra aplicaci\u00f3n. Mientras tanto, el n\u00famero de llamadas se ha mantenido aproximadamente al mismo nivel. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/80772afa0643b29f5314a2482c9dfe0d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aqu\u00ed es fundamental entender c\u00f3mo hacer correctamente estas migraciones. Y es necesario realizarlas. Hacemos estas migraciones de manera bastante constante.<\/p>\n<p><\/p>\n<ul>\n<li>No se realizan autom\u00e1ticamente tales migraciones grandes. Siempre deben estar controladas. <\/li>\n<li>Es necesario el control por parte de una persona capacitada. Si tienes un DBA en tu equipo, que lo haga \u00e9l. Esa es su funci\u00f3n. Si no lo tienes, que lo realice la persona m\u00e1s experimentada que sepa c\u00f3mo trabajar con bases de datos. <\/li>\n<li>El nuevo esquema de la base de datos, incluso si solo actualizamos una columna, siempre lo preparamos por etapas, es decir, con anticipaci\u00f3n antes de implementar una nueva versi\u00f3n de la aplicaci\u00f3n:<\/li>\n<li>Se a\u00f1aden nuevos campos en los que se registrar\u00e1n precisamente los datos actualizados. <\/li>\n<li>Transferimos datos del campo antiguo al nuevo en peque\u00f1as partes. \u00bfPor qu\u00e9 lo hacemos? En primer lugar, siempre controlamos este proceso. Sabemos cu\u00e1ntos lotes hemos transferido y cu\u00e1nto nos queda. <\/li>\n<li>El segundo efecto positivo es que entre cada lote cerramos una transacci\u00f3n, abrimos una nueva y esto permite que el autovacuum procese la tabla y marque las filas muertas para su reutilizaci\u00f3n. <\/li>\n<li>Para las filas que aparecer\u00e1n durante el funcionamiento de la aplicaci\u00f3n (todav\u00eda est\u00e1 operando la antigua) a\u00f1adimos un trigger que graba nuevos valores en los nuevos campos. En nuestro caso, esto implica multiplicar el valor antiguo por cien. <\/li>\n<li>Si somos realmente tercos y queremos usar el mismo campo, al finalizar todas las migraciones y antes de implementar la nueva versi\u00f3n de la aplicaci\u00f3n, simplemente renombramos los campos. Los antiguos a alg\u00fan nombre inventado y los nuevos campos los renombramos a los antiguos. <\/li>\n<li>Y solo despu\u00e9s de eso lanzamos la nueva versi\u00f3n de la aplicaci\u00f3n. <\/li>\n<\/ul>\n<p><\/p>\n<p>Y de esta manera, no tendremos bloat y no perderemos rendimiento. <\/p>\n<p><\/p>\n<p>Aqu\u00ed concluye la tercera historia. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" 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>Y ahora, un poco m\u00e1s sobre las herramientas que mencion\u00e9 en la primera historia. <\/p>\n<p><\/p>\n<p>Antes de buscar el bloat, es imprescindible instalar la extensi\u00f3n. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/pgstattuple.html\">pgstattuple<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Para que no tengan que inventar consultas, ya hemos escrito estas consultas en nuestro trabajo. Pueden utilizarlas. Aqu\u00ed se presentan dos consultas. <\/p>\n<p><\/p>\n<ul>\n<li>La primera tarda un poco m\u00e1s en ejecutarse, pero te mostrar\u00e1 los valores exactos de bloat en la tabla. <\/li>\n<li>La segunda es m\u00e1s r\u00e1pida y muy efectiva cuando necesitas evaluar r\u00e1pidamente si hay bloat o no en la tabla. Y debes entender que el bloat en la tabla de Postgres siempre est\u00e1 presente. Es una caracter\u00edstica de su modelo MVCC. <\/li>\n<li>Y un 20% de bloat es normal para las tablas en la mayor\u00eda de los casos. Es decir, no deber\u00edas preocuparte y comprimir esta tabla. <\/li>\n<\/ul>\n<p><\/p>\n<p>Hemos entendido c\u00f3mo identificar las tablas que se han inflado, especialmente aquellas que han crecido con datos innecesarios. <\/p>\n<p><\/p>\n<p>Ahora hablemos de c\u00f3mo corregir el bloat:<\/p>\n<p><\/p>\n<ul>\n<li>Si tenemos una tabla peque\u00f1a y discos buenos, es decir, si la tabla est\u00e1 por debajo de un gigabyte, es perfectamente posible utilizar VACUUM FULL. Te tomar\u00e1 un bloqueo exclusivo sobre la tabla durante unos segundos y listo, pero har\u00e1 el trabajo de manera r\u00e1pida y efectiva. \u00bfQu\u00e9 hace VACUUM FULL? Toma un bloqueo exclusivo en la tabla y reescribe las filas vivas desde las tablas antiguas a una nueva tabla. Y al final intercambia las tablas. Elimina los archivos antiguos y sustituye lo nuevo por lo viejo. Pero durante su ejecuci\u00f3n, toma un bloqueo exclusivo de la tabla. Esto significa que no podr\u00e1s hacer nada con esa tabla: ni escribir, ni leer, ni modificar. Adem\u00e1s, VACUUM FULL requiere espacio adicional en disco para registrar los datos.<\/li>\n<li>La siguiente herramienta <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">pg_repack<\/a><\/noindex>es muy similar a VACUUM FULL en su principio, ya que tambi\u00e9n reescribe datos de archivos antiguos a nuevos y los intercambia en la tabla. Pero no toma un bloqueo exclusivo sobre la tabla al inicio de su ejecuci\u00f3n, sino que solo lo hace cuando ya tiene datos listos para intercambiar. Sus requisitos de recursos de almacenamiento son similares a los de VACUUM FULL. Necesitar\u00e1s espacio adicional en disco, lo cual puede ser cr\u00edtico si tienes tablas de varios terabytes. Adem\u00e1s, es bastante exigente en cuanto al uso del procesador, debido a que realiza trabajo activo de entrada y salida. <\/li>\n<li>La tercera utilidad es <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">pgcompacttable<\/a><\/noindex>. Es m\u00e1s cuidadosa con los recursos porque funciona con principios diferentes. La esencia principal de pgcompacttable es que, a trav\u00e9s de actualizaciones en la tabla, mueve todas las filas vivas al comienzo de la tabla. Luego ejecuta un vacuum en esta tabla, porque sabemos que al principio est\u00e1n las vivos y al final las muertas. El vacuum recorta esa parte final, es decir, no requiere mucho espacio adicional en disco. Y adem\u00e1s, se puede optimizar a\u00fan m\u00e1s en cuanto a recursos. <\/li>\n<\/ul>\n<p><\/p>\n<p>Todo est\u00e1 con las herramientas. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/4187915e54e54a0b85a342fe0280f78f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Si te parece interesante el tema de bloat y quieres profundizar m\u00e1s, aqu\u00ed tienes algunos enlaces \u00fatiles:<\/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 es la presentaci\u00f3n de un colega. Es general sobre a d\u00f3nde va el espacio en Postgres durante su funcionamiento y vida. Hay una secci\u00f3n t\u00e9cnica muy extensa y detallada para administradores de bases de datos sobre el bloat. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pg-utils\">https:\/\/github.com\/dataegret\/pg-utils<\/a><\/noindex> \u2013 es un enlace a nuestro repositorio, donde almacenamos un mont\u00f3n de scripts \u00fatiles para verificar el estado de la base de datos. All\u00ed puedes encontrar scripts para buscar bloat. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">Tercero<\/a><\/noindex> y <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">cuatro<\/a><\/noindex> enlaces a herramientas que te ayudar\u00e1n a optimizar las tablas. <\/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 es una publicaci\u00f3n de un colega. All\u00ed analiza de manera bastante seria y t\u00e9cnica el bloat, ya a nivel cercano a los administradores. <\/li>\n<\/ul>\n<p><\/p>\n<p>Aqu\u00ed intent\u00e9 mostrar un aspecto preocupante para los desarrolladores, porque ellos son nuestros principales clientes de bases de datos y deben entender las consecuencias de sus acciones. Espero haberlo logrado. \u00a1Gracias por su atenci\u00f3n!<\/p>\n<p><\/p>\n<p>Preguntas<\/p>\n<p><\/p>\n<p><em>\u00a1Gracias por la presentaci\u00f3n! Hablaste sobre c\u00f3mo identificar problemas. \u00bfC\u00f3mo se pueden prevenir? Es decir, tuve una situaci\u00f3n en la que las consultas se quedaban colgadas no solo porque estaban accediendo a servicios externos. Tambi\u00e9n hab\u00eda algunos joins absurdos. Hubo consultas peque\u00f1as e inocentes que estuvieron colgadas durante un d\u00eda, y luego comenzaban a causar problemas. Es decir, se parece mucho a lo que describes. \u00bfC\u00f3mo se puede monitorear esto? \u00bfSe tiene que estar mirando constantemente qu\u00e9 consulta se cuelga? \u00bfC\u00f3mo se puede prevenir?<\/em><\/p>\n<p><\/p>\n<p>En este caso, es una tarea para los administradores de tu empresa, no necesariamente para el DBA.<\/p>\n<p><\/p>\n<p><em>Soy administrador.<\/em><\/p>\n<p><\/p>\n<p>En PostgreSQL hay una vista llamada pg_stat_activity, donde se muestran las consultas colgadas. All\u00ed puedes ver cu\u00e1nto tiempo llevan colgadas.<\/p>\n<p><\/p>\n<p><em>\u00bfTengo que entrar cada 5 minutos y revisar?<\/em><\/p>\n<p><\/p>\n<p>Configura cron y verifica. Si tienes una consulta prolongada, env\u00eda un correo y listo. Es decir, no necesitas mirar manualmente, puedes automatizarlo. Recibir\u00e1s un correo y reaccionar\u00e1s a \u00e9l. Tambi\u00e9n puedes disparar autom\u00e1ticamente.<\/p>\n<p><\/p>\n<p><em>\u00bfHay razones evidentes de por qu\u00e9 esto sucede?<\/em><\/p>\n<p><\/p>\n<p>He enumerado algunas. Otros ejemplos son m\u00e1s complejos. Y la conversaci\u00f3n puede prolongarse.<\/p>\n<p><\/p>\n<p><em>\u00a1Gracias por la presentaci\u00f3n! Quer\u00eda preguntar sobre la utilidad pg_repack. Si no hace un bloqueo exclusivo, entonces...<\/em><\/p>\n<p><\/p>\n<p>S\u00ed, hace un bloqueo exclusivo. <\/p>\n<p><\/p>\n<p>\u2026 <em>entonces potencialmente puedo perder datos. \u00bfMi aplicaci\u00f3n no deber\u00eda escribir nada en ese momento?<\/em><\/p>\n<p><\/p>\n<p>No, funciona sin problemas con la tabla, es decir, pg_repack primero traslada todas las filas activas que hay. Naturalmente, hay alguna escritura en la tabla. Simplemente a\u00f1ade ese \u00faltimo fragmento. <\/p>\n<p><\/p>\n<p><em>Es decir, \u00bfal final lo hace?<\/em><\/p>\n<p><\/p>\n<p>Al final, toma un bloqueo exclusivo para intercambiar esos archivos. <\/p>\n<p><\/p>\n<p><em>\u00bfEso ser\u00e1 m\u00e1s r\u00e1pido que VACUUM FULL?<\/em><\/p>\n<p><\/p>\n<p>VACUUM FULL, tan pronto como se inicia, toma inmediatamente un bloqueo exclusivo. Y no lo libera hasta que haya terminado. En cambio, pg_repack toma un bloqueo exclusivo solo en el momento de reemplazar los archivos. En ese momento, no podr\u00e1s escribir, pero los datos no se perder\u00e1n, todo estar\u00e1 bien. <\/p>\n<p><\/p>\n<p><em>\u00a1Hola! Hablaste sobre el funcionamiento del autovacuum. Hab\u00eda un gr\u00e1fico con celdas rojas, amarillas y verdes. Es decir, las amarillas las marc\u00f3 como eliminadas. \u00bfY, por lo tanto, se puede escribir algo nuevo en ellas?<\/em><\/p>\n<p><\/p>\n<p>S\u00ed. Postgres no elimina filas. Tiene esa especificidad. Si actualizamos una fila, marcamos la antigua como eliminada. Se inserta el id de la transacci\u00f3n que cambi\u00f3 esa fila, y escribimos una nueva fila. Y tenemos sesiones que potencialmente pueden leerlas. En alg\u00fan momento, estas se vuelven muy antiguas. Y la esencia del trabajo del autovacuum es que repasa estas filas y las marca como innecesarias. Y all\u00ed se pueden sobrescribir los datos. <\/p>\n<p><\/p>\n<p><em>Entiendo. Pero la pregunta es un poco diferente. No termin\u00e9. Supongamos que tenemos una tabla. Tiene campos de tama\u00f1o variable. Y si intento insertar algo nuevo, podr\u00eda no caber en la antigua celda.<\/em> <\/p>\n<p><\/p>\n<p>No, de todas formas se actualiza toda la l\u00ednea. En Postgres hay dos modelos de almacenamiento de datos. Se elige seg\u00fan el tipo de datos. Hay datos que se almacenan directamente en la tabla y hay tambi\u00e9n tos-datos. Son grandes vol\u00famenes de datos: texto, json. Se almacenan en tablas separadas. Y con estas tablas ocurre la misma historia con el bloat, es decir, todo lo mismo. Simplemente est\u00e1n separadas. <\/p>\n<p><\/p>\n<p><em>\u00a1Gracias por la presentaci\u00f3n! \u00bfQu\u00e9 tan aceptable es utilizar la opci\u00f3n statement timeout para limitar la duraci\u00f3n de las consultas?<\/em><\/p>\n<p><\/p>\n<p>Es muy aceptable. Lo utilizamos en todas partes. Y dado que no tenemos nuestros propios servicios, proporcionamos soporte remoto, hay clientes bastante variados. Y a todos les satisface esto. Es decir, tenemos tareas en cron que hacen verificaciones. Simplemente se acuerda con el cliente la duraci\u00f3n de las sesiones, antes de la cual no desconectamos. Esto puede ser un minuto, puede ser 10 minutos. Depende de la carga en la base de datos y su objetivo. Pero todos usamos pg_stat_activity.<\/p>\n<p><\/p>\n<p><em>\u00a1Gracias por la presentaci\u00f3n! Estoy intentando adaptar su informe a mis aplicaciones. Y parece que comenzamos una transacci\u00f3n en todas partes, la terminamos expl\u00edcitamente en todas partes. Si hay alguna excepci\u00f3n, igual ocurre un rollback. Y aqu\u00ed me he puesto a pensar. Despu\u00e9s de todo, una transacci\u00f3n puede iniciarse de manera impl\u00edcita. Es una pista para la chica, supongo. Si simplemente actualizo un registro, \u00bfla transacci\u00f3n se iniciar\u00e1 en PostgreSQL y solo se completar\u00e1 cuando se interrumpa la conexi\u00f3n?<\/em><\/p>\n<p><\/p>\n<p>Si hablas ahora del nivel de la aplicaci\u00f3n, eso depende del controlador que est\u00e9s usando, del ORM que se est\u00e9 utilizando. Hay muchas configuraciones. Si tienes activado el auto commit on, entonces la transacci\u00f3n se inicia y se cierra de inmediato.<\/p>\n<p><\/p>\n<p><em>Es decir, \u00bfse cierra inmediatamente despu\u00e9s de la actualizaci\u00f3n?<\/em><\/p>\n<p><\/p>\n<p>Eso depende de la configuraci\u00f3n. Ya he mencionado una configuraci\u00f3n. Es el auto commit on. Es bastante com\u00fan. Si est\u00e1 habilitada, la transacci\u00f3n se abre y se cierra. Si no has dicho expl\u00edcitamente \"start transaction\" y \"end transaction\", sino que has ejecutado simplemente en la sesi\u00f3n la consulta. <\/p>\n<p><\/p>\n<p><em>\u00a1Hola! \u00a1Gracias por la presentaci\u00f3n! Supongamos que tenemos una base de datos que se inflando y aqu\u00ed en el servidor se acaba el espacio. \u00bfHay alguna herramienta para solucionar esta situaci\u00f3n?<\/em> <\/p>\n<p><\/p>\n<p>El espacio en el servidor, en principio, debe ser monitoreado. <\/p>\n<p><\/p>\n<p><em>Por ejemplo, el DBA fue a tomar t\u00e9, estaba de vacaciones, etc.<\/em><\/p>\n<p><\/p>\n<p>Cuando se crea un sistema de archivos, se reserva al menos un espacio de reserva donde no se escriben datos. <\/p>\n<p><\/p>\n<p><em>\u00bfY si se reduce a cero?<\/em><\/p>\n<p><\/p>\n<p>Ese espacio se llama espacio reservado, es decir, se puede liberar y, dependiendo de cu\u00e1nto se haya creado, obtienes espacio libre. Por defecto no s\u00e9 cu\u00e1nto hay. En otro caso, se necesitan discos para que tengas espacio para realizar una recuperaci\u00f3n. Se puede eliminar alguna tabla que est\u00e9s seguro de que no necesitas. <\/p>\n<p><\/p>\n<p><em>\u00bfNo hay otras herramientas?<\/em><\/p>\n<p><\/p>\n<p>Siempre es un trabajo manual. Y en el lugar se determina qu\u00e9 es lo mejor hacer, porque hay datos cr\u00edticos y no cr\u00edticos. Y para cada base y aplicaci\u00f3n que trabaja con ella, depende del negocio. Siempre se decide en el lugar. <\/p>\n<p><\/p>\n<p><em>\u00a1Gracias por la presentaci\u00f3n! Tengo dos preguntas. En primer lugar, mostraste diapositivas donde se mostraba que en caso de transacciones colgadas, tanto el volumen del espacio de tabla como el tama\u00f1o del \u00edndice aumentan. Y luego en la presentaci\u00f3n hab\u00eda un mont\u00f3n de utilidades que empaquetan la tabla. \u00bfY qu\u00e9 pasa con el \u00edndice?<\/em><\/p>\n<p><\/p>\n<p>Tambi\u00e9n las empaquetan. <\/p>\n<p><\/p>\n<p><em>Pero el VACUUM no afecta al \u00edndice, \u00bfverdad?<\/em><\/p>\n<p><\/p>\n<p>Algunos trabajan con el \u00edndice. Por ejemplo, pg_rapack, pgcompacttable. El VACUUM reconstruye los \u00edndices, los afecta. La esencia del VACUUM FULL es reescribir todo, es decir, trabaja con todos. <\/p>\n<p><\/p>\n<p><em>Y la segunda pregunta. No entend\u00ed por qu\u00e9 los informes en las r\u00e9plicas dependen tanto de la misma replicaci\u00f3n. Pensaba que los informes eran solo lecturas, y la replicaci\u00f3n, escrituras.<\/em> <\/p>\n<p><\/p>\n<p>\u00bfD\u00f3nde surge el conflicto de replicaci\u00f3n? Tenemos un Maestro donde ocurren los procesos. Hay un autovacuum. \u00bfQu\u00e9 hace realmente el autovacuum? Elimina algunas l\u00edneas antiguas. Si en ese momento en la r\u00e9plica hay una solicitud que lee estas l\u00edneas antiguas, y en el Maestro ocurri\u00f3 una situaci\u00f3n en la que el autovacuum marc\u00f3 estas l\u00edneas como posibles para reescribir, entonces las reescribimos. Y tenemos un paquete de datos que debe reescribir esas l\u00edneas necesarias para la solicitud en la r\u00e9plica; el proceso de replicaci\u00f3n esperar\u00e1 el tiempo de espera que configuraste. Luego, PostgreSQL decidir\u00e1 qu\u00e9 es m\u00e1s importante para \u00e9l. Y la replicaci\u00f3n es m\u00e1s importante que la solicitud, por lo que la solicitud se cancelar\u00e1 para realizar esos cambios en la r\u00e9plica. <\/p>\n<p><\/p>\n<p><em>Andrei, tengo una pregunta. \u00bfEsos gr\u00e1ficos maravillosos que mostraste durante la presentaci\u00f3n, son el resultado de alg\u00fan software tuyo? \u00bfCon qu\u00e9 se construyeron los gr\u00e1ficos?<\/em><\/p>\n<p><\/p>\n<p>Este es un servicio <noindex><a rel=\"nofollow\" href=\"https:\/\/okmeter.io\/\">Okmeter<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><em>\u00bfEs un producto comercial?<\/em><\/p>\n<p><\/p>\n<p>S\u00ed. Es un producto comercial.<\/p>\n<p>Fuente: <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.2 - 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\/es\/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.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\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\/es\/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\udd47Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql. Andrei Salnikov | ProHoster","description":"Te propongo que revises la transcripci\u00f3n de la presentaci\u00f3n de principios de 2016 de Andrei Salnikov \"Errores t\u00edpicos en aplicaciones que conducen a bloat en postgresql\". En esta presentaci\u00f3n, discutir\u00e9 los aspectos principales.","canonical_url":"https:\/\/prohoster.info\/es\/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":"es_ES","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\/es\/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\/es\/wp-json\/wp\/v2\/posts\/81089","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=81089"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/81089\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/81090"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=81089"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=81089"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=81089"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}