{"id":71792,"date":"2023-11-23T13:27:33","date_gmt":"2023-11-23T12:27:33","guid":{"rendered":"https:\/\/kinsta.com\/es\/?p=71792&#038;preview=true&#038;preview_id=71792"},"modified":"2023-11-30T13:39:18","modified_gmt":"2023-11-30T12:39:18","slug":"plan-de-mantenimiento-de-la-base-de-datos","status":"publish","type":"post","link":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/","title":{"rendered":"Configuraci\u00f3n de Planes de Mantenimiento de Bases de Datos para PostgreSQL en Node.js"},"content":{"rendered":"<p>A medida que evoluciona el desarrollo de aplicaciones, las bases de datos se erigen en el n\u00facleo de la mayor\u00eda de las aplicaciones, almacenando y gestionando datos cruciales para los negocios digitales. A medida que estos datos crecen y se hacen m\u00e1s complejos, garantizar la eficiencia de tu base de datos es vital para satisfacer las necesidades de tu aplicaci\u00f3n.<\/p>\n<p>Ah\u00ed es donde entra en juego la idea del mantenimiento de la base de datos. El mantenimiento de la base de datos implica tareas como la limpieza, las copias de seguridad y la optimizaci\u00f3n de los \u00edndices para aumentar el rendimiento.<\/p>\n<p>Este art\u00edculo ofrece informaci\u00f3n valiosa sobre los disparadores de mantenimiento y presenta instrucciones pr\u00e1cticas de configuraci\u00f3n. Explica el proceso de implementaci\u00f3n de varias tareas de mantenimiento de bases de datos, como hacer copias de seguridad de los datos, reconstruir \u00edndices, archivar y limpiar datos utilizando <a href=\"https:\/\/kinsta.com\/es\/secciones\/postgresql\/\">PostgreSQL<\/a>, integrado con un disparador API en una aplicaci\u00f3n <a href=\"https:\/\/kinsta.com\/es\/secciones\/node-js\/\">Node.js<\/a>.<\/p>\n<div><\/div><kinsta-auto-toc heading=\"Table of Contents\" exclude=\"last\" list-style=\"arrow\" selector=\"h2\" count-number=\"-1\"><\/kinsta-auto-toc>\n<h2>Entender los Disparadores<\/h2>\n<p>Antes de crear operaciones de mantenimiento para tu base de datos, es importante comprender las distintas formas en que se pueden disparar. Cada desencadenante sirve para fines distintos a la hora de facilitar las tareas de mantenimiento. Los tres disparadores principales que se utilizan habitualmente son:<\/p>\n<ul>\n<li><strong>Manual, basado en API<\/strong>: Este disparador te permite ejecutar operaciones puntuales mediante una llamada a la API. Es \u00fatil en situaciones como la restauraci\u00f3n de una copia de seguridad de la base de datos o la reconstrucci\u00f3n de \u00edndices cuando el rendimiento cae repentinamente.<\/li>\n<li><strong>Programado (como CRON)<\/strong>: Este disparador te permite automatizar actividades de mantenimiento programadas durante periodos de bajo tr\u00e1fico de usuarios. Es ideal para ejecutar operaciones que consumen muchos recursos, como el archivado y la limpieza. Puedes utilizar paquetes como <a href=\"https:\/\/www.npmjs.com\/package\/node-schedule\" target=\"_blank\" rel=\"noopener noreferrer\">node-schedule<\/a> para configurar programaciones en Node.js que disparen las operaciones autom\u00e1ticamente cuando sea necesario.<\/li>\n<li><strong>Notificaciones de la base de datos<\/strong>: Este disparador te permite realizar operaciones de mantenimiento en respuesta a cambios en la base de datos. Por ejemplo, cuando un usuario publica un comentario en una plataforma, los datos guardados pueden disparar instant\u00e1neamente comprobaciones de caracteres irregulares, lenguaje ofensivo o emojis. Implementar esta funcionalidad en Node.js es posible utilizando paquetes como <a href=\"https:\/\/github.com\/andywer\/pg-listen\" target=\"_blank\" rel=\"noopener noreferrer\">pg-listen<\/a>.<\/li>\n<\/ul>\n<h2>Requisitos Previos<\/h2>\n<p>Para seguir esta gu\u00eda, debes tener las siguientes herramientas en tu ordenador local:<\/p>\n<ul>\n<li><a href=\"https:\/\/kinsta.com\/es\/blog\/instalar-git\/\">Git<\/a>: Para gestionar el control de versiones del c\u00f3digo fuente de tu aplicaci\u00f3n<\/li>\n<li><a href=\"https:\/\/kinsta.com\/es\/blog\/como-instalar-node-js\/\">Node.js<\/a>: Para construir tu aplicaci\u00f3n backend<\/li>\n<li><a href=\"https:\/\/www.postgresql.org\/docs\/current\/app-psql.html\" target=\"_blank\" rel=\"noopener noreferrer\">psql<\/a>: Para interactuar con tu base de datos PostgreSQL remota utilizando tu terminal<\/li>\n<li><a href=\"https:\/\/www.pgadmin.org\/download\/\" target=\"_blank\" rel=\"noopener noreferrer\">PGAdmin<\/a> (Opcional): Para interactuar con tu base de datos PostgreSQL remota utilizando una Interfaz Gr\u00e1fica de Usuario (GUI).<\/li>\n<\/ul>\n<h3>Crear y Alojar una Aplicaci\u00f3n Node.js<\/h3>\n<p>Vamos a crear un proyecto Node.js, hacer commit en GitHub y configurar un canal de despliegue autom\u00e1tico en Kinsta. Tambi\u00e9n necesitas aprovisionar una <a href=\"https:\/\/sevalla.com\/database-hosting\/\">base de datos PostgreSQL en Kinsta<\/a> para probar tus rutinas de mantenimiento en ella.<\/p>\n<p>Empieza creando un nuevo directorio en tu sistema local utilizando el siguiente comando:<\/p>\n<pre><code class=\"language-bash\">mkdir node-db-maintenance<\/code><\/pre>\n<p>A continuaci\u00f3n, cambia a la carpeta reci\u00e9n creada y ejecuta el siguiente comando para crear un nuevo proyecto:<\/p>\n<pre><code class=\"language-bash\">cd node-db-maintenance\nyarn init -y # or npm init -y<\/code><\/pre>\n<p>Esto inicializa un proyecto Node.js para ti con la configuraci\u00f3n por defecto. Ahora puedes instalar las dependencias necesarias ejecutando el siguiente comando:<\/p>\n<pre><code class=\"language-bash\">yarn add express pg nodemon dotenv<\/code><\/pre>\n<p>Aqu\u00ed tienes una breve descripci\u00f3n de cada paquete:<\/p>\n<ul>\n<li><code>express<\/code>: te permite configurar una API REST basada en Express.<\/li>\n<li><code>pg<\/code>: te permite interactuar con una base de datos PostgreSQL a trav\u00e9s de tu aplicaci\u00f3n Node.js.<\/li>\n<li><code>nodemon<\/code> permite que tu versi\u00f3n de desarrollo (dev build) se actualice a medida que desarrollas tu aplicaci\u00f3n, liber\u00e1ndote de la constante necesidad de parar e iniciar tu aplicaci\u00f3n cada vez que haces un cambio.<\/li>\n<li><code>dotenv<\/code>: te permite cargar variables de entorno de un archivo <strong>.env<\/strong> en tu objeto <code>process.env<\/code>.<\/li>\n<\/ul>\n<p>A continuaci\u00f3n, a\u00f1ade los siguientes scripts en tu archivo <strong>package.json<\/strong> para que puedas iniciar f\u00e1cilmente tu servidor dev y ejecutar tambi\u00e9n tu servidor en producci\u00f3n:<\/p>\n<pre><code class=\"language-js\">{\n    \/\/ ... \n    \"scripts\": {\n      \"start-dev\": \"nodemon index.js\",\n      \"start\": \"NODE_ENV=production node index.js\"\n  },\n  \/\/ \u2026\n}<\/code><\/pre>\n<p>Ahora puedes crear un archivo <strong>index.js<\/strong> que contenga el c\u00f3digo fuente de tu aplicaci\u00f3n. Pega el siguiente c\u00f3digo en el archivo:<\/p>\n<pre><code class=\"language-js\">const express = require(\"express\")\nconst dotenv = require('dotenv');\n\nif (process.env.NODE_ENV !== 'production') dotenv.config();\nconst app = express()\nconst port = process.env.PORT || 3000\n\napp.get(\"\/health\", (req, res) =&gt; res.json({status: \"UP\"}))\n\napp.listen(port, () =&gt; {\n    console.log(`Server running at port: ${port}`);\n});<\/code><\/pre>\n<p>Este c\u00f3digo anterior inicializa un servidor <a href=\"https:\/\/kinsta.com\/es\/blog\/que-es-express\/\">Express<\/a> y configura variables de entorno utilizando el paquete <code>dotenv<\/code> si no est\u00e1 en modo de producci\u00f3n. Tambi\u00e9n configura una ruta <code>\/health<\/code> que devuelve un objeto JSON <code>{status: \"UP\"}<\/code>. Por \u00faltimo, inicia la aplicaci\u00f3n utilizando la funci\u00f3n <code>app.listen()<\/code> para escuchar en el puerto especificado, por defecto <code>3000<\/code> si no se proporciona ning\u00fan puerto a trav\u00e9s de la variable de entorno.<\/p>\n<p>Ahora que ya tienes lista una aplicaci\u00f3n b\u00e1sica, inicializa un nuevo repositorio git con tu proveedor git preferido (<a href=\"https:\/\/docs.sevalla.com\/applications\/git\/bitbucket#grant-access-to-the-kinsta-bitbucket-application\">BitBucket<\/a>, <a href=\"https:\/\/docs.sevalla.com\/applications\/git\/github#authenticate-and-authorize\">GitHub<\/a> o <a href=\"https:\/\/docs.sevalla.com\/applications\/git\/gitlab#authorize-the-kinsta-gitlab-application\">GitLab<\/a>) y env\u00eda tu c\u00f3digo. Kinsta soporta el despliegue de aplicaciones desde todos estos proveedores git. Para este art\u00edculo, vamos a utilizar GitHub.<\/p>\n<p>Cuando tu repositorio est\u00e9 listo, sigue estos pasos para desplegar tu aplicaci\u00f3n en Kinsta:<\/p>\n<ol>\n<li>Inicia sesi\u00f3n o crea una cuenta para ver tu panel <a href=\"https:\/\/my.kinsta.com\/?lang=es\">MyKinsta<\/a>.<\/li>\n<li>Autoriza a Kinsta con tu proveedor de Git.<\/li>\n<li>En la barra lateral izquierda, haz clic en <strong>Aplicaciones<\/strong> y luego en <strong>A\u00f1adir aplicaci\u00f3n<\/strong>.<\/li>\n<li>Selecciona el repositorio y la rama desde la que deseas desplegar.<\/li>\n<li>Selecciona una de las ubicaciones de centros de datos disponibles en la lista de 27 opciones. Kinsta detecta autom\u00e1ticamente la configuraci\u00f3n de construcci\u00f3n de tus aplicaciones a trav\u00e9s de <a href=\"https:\/\/kinsta.com\/es\/changelog\/nixpacks\/\">Nixpacks<\/a>.<\/li>\n<li>Elige los recursos de tu aplicaci\u00f3n, como RAM y espacio en disco.<\/li>\n<li>Haz clic en <strong>Crear aplicaci\u00f3n<\/strong>.<\/li>\n<\/ol>\n<p>Una vez completado el despliegue, copia el enlace de la aplicaci\u00f3n desplegada y navega a <code>\/health<\/code>. Deber\u00edas ver el siguiente JSON en tu navegador:<\/p>\n<pre><code class=\"language-js\">{status: \"UP\"}<\/code><\/pre>\n<p>Esto indica que la aplicaci\u00f3n se ha configurado correctamente.<\/p>\n<h3>Configurar una Instancia PostgreSQL en Kinsta<\/h3>\n<p>Kinsta proporciona una interfaz sencilla para aprovisionar instancias de bases de datos. Empieza por crear una nueva <a href=\"https:\/\/kinsta.com\/es\/suscripcion\/\">cuenta Kinsta<\/a> si a\u00fan no tienes una. A continuaci\u00f3n, sigue los siguientes pasos:<\/p>\n<ol>\n<li>Accede a tu panel MyKinsta.<\/li>\n<li>En la barra lateral izquierda, haz clic en <strong>Bases de datos<\/strong> y luego en <strong>A\u00f1adir base de datos<\/strong>.<\/li>\n<li>Selecciona <strong>PostgreSQL<\/strong> como tipo de Base de Datos y elige la versi\u00f3n que prefieras. Elige un nombre para tu base de datos y modifica el nombre de usuario y la contrase\u00f1a si lo deseas.<\/li>\n<li>Selecciona una ubicaci\u00f3n de centro de datos de la lista de 27 opciones.<\/li>\n<li>Elige el tama\u00f1o de tu base de datos.<\/li>\n<li>Haz clic en <strong>Crear base de datos<\/strong>.<\/li>\n<\/ol>\n<p>Una vez creada la base de datos, aseg\u00farate de recuperar el host, el puerto, el nombre de usuario y la contrase\u00f1a de la base de datos.<\/p>\n<figure id=\"attachment_168402\" aria-describedby=\"caption-attachment-168402\" style=\"width: 1024px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-168402 size-large\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2023\/11\/database-credentials-from-kinsta-1024x435.jpg\" alt=\"La pantalla muestra el nombre de host externo, el puerto, el nombre de usuario, la contrase\u00f1a, el nombre de la base de datos y una cadena de conexi\u00f3n externa para la base de datos que se cre\u00f3 en Kinsta.\" width=\"1024\" height=\"435\"><figcaption id=\"caption-attachment-168402\" class=\"wp-caption-text\">Credenciales de la base de datos generadas por Kinsta<\/figcaption><\/figure>\n<p>A continuaci\u00f3n, puedes introducir estos valores en tu CLI psql (o GUI PGAdmin) para gestionar la base de datos. Para probar tu c\u00f3digo localmente, crea un archivo <strong>.env<\/strong> en el directorio root de tu proyecto y almacena en \u00e9l los siguientes secretos:<\/p>\n<pre><code class=\"language-bash\">DB_USER_NAME=your database user name\nDB_HOST=your database host\nDB_DATABASE_NAME=your database\u2019s name\nDB_PORT=your database port\nPGPASS=your database password<\/code><\/pre>\n<p>Cuando despliegues en Kinsta, deber\u00e1s a\u00f1adir estos valores como <a href=\"https:\/\/docs.sevalla.com\/applications\/overviewenvironment-variables\">variables de entorno<\/a> al despliegue de tu aplicaci\u00f3n.<\/p>\n<p>Para prepararte para las operaciones con la base de datos, descarga y ejecuta <a href=\"https:\/\/github.com\/krharsh17\/node-db-maintenance\/blob\/main\/test-data.sql\" target=\"_blank\" rel=\"noopener noreferrer\">este script SQL<\/a> para crear tablas (usuarios, entradas, comentarios) e insertar datos de ejemplo. Utiliza el siguiente comando, sustituyendo los marcadores de posici\u00f3n por tus datos espec\u00edficos, para a\u00f1adir los datos a tu base de datos PostgreSQL reci\u00e9n creada:<\/p>\n<pre><code class=\"language-bash\">psql -h &lt;host&gt; -p &lt;port&gt; -U &lt;username&gt; -d &lt;db_name&gt; -a -f &lt;sql file e.g. test-data.sql&gt;<\/code><\/pre>\n<p>Aseg\u00farate de introducir el nombre de archivo y la ruta exactos en el comando anterior. La ejecuci\u00f3n de este comando te pide que introduzcas la contrase\u00f1a de tu base de datos para autorizarte.<\/p>\n<p>Una vez que este comando termine de ejecutarse, estar\u00e1s listo para empezar a escribir operaciones para el mantenimiento de tu base de datos. No dudes en enviar tu c\u00f3digo a tu repositorio Git cuando termines con cada operaci\u00f3n para verlo en acci\u00f3n en la plataforma Kinsta.<\/p>\n<h2>Escribir Rutinas de Mantenimiento<\/h2>\n<p>En esta secci\u00f3n se explican varias operaciones de uso com\u00fan para el mantenimiento de bases de datos PostgreSQL.<\/p>\n<h3>1. Crear Copias de Seguridad<\/h3>\n<p>Hacer copias de seguridad peri\u00f3dicas de las bases de datos es una operaci\u00f3n com\u00fan y esencial. Consiste en crear una copia de todo el contenido de la base de datos, que se almacena en una ubicaci\u00f3n segura. Estas copias de seguridad son cruciales para restaurar los datos en caso de p\u00e9rdida accidental o de errores que afecten a su integridad.<\/p>\n<p>Aunque <a href=\"https:\/\/docs.sevalla.com\/databases\/backups\">plataformas como Kinsta ofrecen copias de seguridad automatizadas<\/a> como parte de sus servicios, es importante saber c\u00f3mo configurar una rutina de copia de seguridad personalizada si es necesario.<\/p>\n<p>PostgreSQL ofrece la herramienta <a href=\"https:\/\/www.postgresql.org\/docs\/current\/app-pgdump.html\" target=\"_blank\" rel=\"noopener noreferrer\">pg_dump<\/a> para crear copias de seguridad de la base de datos. Sin embargo, debe ejecutarse directamente desde la l\u00ednea de comandos, y no existe un paquete npm para ella. As\u00ed que tienes que utilizar el paquete <a href=\"https:\/\/www.npmjs.com\/package\/@getvim\/execute\" target=\"_blank\" rel=\"noopener noreferrer\">@getvim\/execute<\/a> para ejecutar el comando <code>pg_dump<\/code> en el entorno local de tu aplicaci\u00f3n Node.<\/p>\n<p>Instala el paquete ejecutando el siguiente comando:<\/p>\n<pre><code class=\"language-bash\">yarn add @getvim\/execute<\/code><\/pre>\n<p>A continuaci\u00f3n, importa el paquete en tu archivo <strong>index.js <\/strong>a\u00f1adiendo esta l\u00ednea de c\u00f3digo en la parte superior:<\/p>\n<pre><code class=\"language-js\">const {execute} = require('@getvim\/execute');<\/code><\/pre>\n<p>Las copias de seguridad se generan como archivos en el sistema de archivos local de tu aplicaci\u00f3n Node. Por tanto, es mejor crear un directorio dedicado para ellas con el nombre de <strong>backup<\/strong> en el directorio root del proyecto.<\/p>\n<p>Ahora, puedes utilizar la siguiente ruta para generar y descargar copias de seguridad de tu base de datos cuando sea necesario:<\/p>\n<pre><code class=\"language-js\">app.get('\/backup', async (req, res) =&gt; {\n\n    \/\/ Create a name for the backup file\n    const fileName = \"database-backup-\" + new Date().valueOf() + \".tar\";\n\n    \/\/ Execute the pg_dump command to generate the backup file\n    execute(\"PGPASSWORD=\" + process.env.PGPASS  + \" pg_dump -U \" + process.env.DB_USER_NAME \n    + \" -d \" + process.env.DB_DATABASE_NAME \n    + \" -h \" + process.env.DB_HOST\n    + \" -p \" + process.env.DB_PORT\n    + \" -f backup\/\" + fileName + \" -F t\"\n\n).then(async () =&gt; {\n        console.log(\"Backup created\");\n        res.redirect(\"\/backup\/\" + fileName)\n    }).catch(err =&gt; {\n        console.log(err);\n        res.json({message: \"Something went wrong\"})\n    })\n\n})<\/code><\/pre>\n<p>Adem\u00e1s, tienes que a\u00f1adir la siguiente l\u00ednea al principio de tu archivo <strong>index.js<\/strong> despu\u00e9s de inicializar la aplicaci\u00f3n Express:<\/p>\n<pre><code class=\"language-js\">app.use('\/backup', express.static('backup'))<\/code><\/pre>\n<p>Esto permite que la carpeta de <strong>backup<\/strong> se sirva est\u00e1ticamente utilizando la funci\u00f3n de middleware <code>express.static<\/code>, permitiendo al usuario descargar los archivos de copia de seguridad generados desde la app Node.<\/p>\n<aside role=\"note\" class=\"wp-block-kinsta-notice is-style-info\">\n            <h3>Info<\/h3>\n        <p>Si encuentras un error <code>server version mismatch<\/code> con PostgreSQL, significa que la versi\u00f3n de la base de datos difiere de la de tu herramienta local <code>pg_dump<\/code>. Resu\u00e9lvelo comprobando tu versi\u00f3n de <code>pg_dump<\/code> y actualizando la herramienta o la base de datos para que coincidan.<\/p>\n<\/aside>\n\n<h3>2. Restaurar Desde una Copia de Seguridad<\/h3>\n<p>Postgres permite restaurar a partir de copias de seguridad utilizando la herramienta de l\u00ednea de comandos <code>pg_restore<\/code>. Sin embargo, tienes que utilizarla a trav\u00e9s del paquete <code>execute<\/code> de forma similar a como utilizaste el comando <code>pg_dump<\/code>. Aqu\u00ed tienes el c\u00f3digo de la ruta:<\/p>\n<pre><code class=\"language-js\">app.get('\/restore', async (req, res) =&gt; {\n\n    const dir = 'backup'\n\n    \/\/ Sort the backup files according to when they were created\n    const files = fs.readdirSync(dir)\n        .filter((file) =&gt; fs.lstatSync(path.join(dir, file)).isFile())\n        .map((file) =&gt; ({ file, mtime: fs.lstatSync(path.join(dir, file)).mtime }))\n        .sort((a, b) =&gt; b.mtime.getTime() - a.mtime.getTime());\n\n    if (!files.length){\n        res.json({message: \"No backups available to restore from\"})\n    }\n\n    const fileName = files[0].file\n\n    \/\/ Restore the database from the chosen backup file\n    execute(\"PGPASSWORD=\" + process.env.PGPASS  + \" pg_restore -cC \"\n    + \"-U \" + process.env.DB_USER_NAME\n    + \" -h \" + process.env.DB_HOST\n    + \" -p \" + process.env.DB_PORT\n    + \" -d postgres backup\/\" + fileName\n)\n\n        .then(async ()=&gt; {\n            console.log(\"Restored\");\n            res.json({message: \"Backup restored\"})\n        }).catch(err=&gt; {\n        console.log(err);\n        res.json({message: \"Something went wrong\"})\n    })\n})<\/code><\/pre>\n<p>El fragmento de c\u00f3digo anterior busca primero los archivos almacenados en el directorio local de la <strong>copia de seguridad<\/strong>. Despu\u00e9s, los ordena por la fecha en que se crearon para encontrar el archivo de copia de seguridad m\u00e1s reciente. Por \u00faltimo, utiliza el paquete <code>execute<\/code> para restaurar el archivo de copia de seguridad elegido.<\/p>\n<p>Aseg\u00farate de a\u00f1adir los siguientes imports a tu archivo <strong>index.js<\/strong> para que se importen los m\u00f3dulos necesarios para acceder al sistema de archivos local, permitiendo que la funci\u00f3n se ejecute correctamente:<\/p>\n<pre><code class=\"language-js\">const fs = require('fs')\nconst path = require('path')<\/code><\/pre>\n<h3>3. Reconstruir un \u00cdndice<\/h3>\n<p>Los \u00edndices de las tablas Postgres a veces se corrompen, y el rendimiento de la base de datos se degrada. Esto puede deberse a fallos o errores de software. A veces, los \u00edndices tambi\u00e9n pueden hincharse debido a demasiadas p\u00e1ginas vac\u00edas o casi vac\u00edas.<\/p>\n<p>En estos casos, tienes que reconstruir el \u00edndice para asegurarte de que obtienes el m\u00e1ximo rendimiento de tu instancia Postgres.<\/p>\n<p>Postgres ofrece el comando <a href=\"https:\/\/www.postgresql.org\/docs\/current\/sql-reindex.html\" target=\"_blank\" rel=\"noopener noreferrer\">REINDEX<\/a> para este fin. Puedes utilizar el paquete <a href=\"https:\/\/node-postgres.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">node-postgres<\/a> para ejecutar este comando (y tambi\u00e9n para ejecutar otras operaciones m\u00e1s adelante), as\u00ed que inst\u00e1lalo ejecutando primero el siguiente comando:<\/p>\n<pre><code class=\"language-bash\">yarn add pg<\/code><\/pre>\n<p>A continuaci\u00f3n, a\u00f1ade las siguientes l\u00edneas al principio del archivo <strong>index.js<\/strong>, debajo de las importaciones, para inicializar correctamente la conexi\u00f3n a la base de datos:<\/p>\n<pre><code class=\"language-js\">const {Client} = require('pg')\nconst client = new Client({\n    user: process.env.DB_USER_NAME,\n    host: process.env.DB_HOST,\n    database: process.env.DB_DATABASE_NAME,\n    password: process.env.PGPASS,\n    port: process.env.DB_PORT\n})\n\n\n\nclient.connect(err =&gt; {\n    if (err) throw err;\n    console.log(\"Connected!\")\n})<\/code><\/pre>\n<p>La implementaci\u00f3n de esta operaci\u00f3n es bastante sencilla:<\/p>\n<pre><code class=\"language-js\">app.get(\"\/reindex\", async (req, res) =&gt; {\n\n    \/\/ Run the REINDEX command as needed\n    await client.query(\"REINDEX TABLE Users;\")\n\n    res.json({message: \"Reindexed table successfully\"})\n})<\/code><\/pre>\n<p>El comando mostrado anteriormente reindexa la tabla Usuarios completa. Puedes personalizar el comando seg\u00fan tus necesidades para reconstruir un \u00edndice concreto o incluso para reindexar toda la base de datos.<\/p>\n<h3>4. Archivo y Purga de Datos<\/h3>\n<p>Para las bases de datos que crecen con el tiempo (y a las que rara vez se accede a los datos hist\u00f3ricos), puede tener sentido establecer rutinas que descarguen los datos antiguos en un lago de datos donde puedan almacenarse y procesarse m\u00e1s c\u00f3modamente.<\/p>\n<p>Los archivos Parquet son un est\u00e1ndar com\u00fan para el almacenamiento y transferencia de datos en muchos lagos de datos. Utilizando la biblioteca <a href=\"https:\/\/www.npmjs.com\/package\/parquetjs\" target=\"_blank\" rel=\"noopener noreferrer\">ParquetJS<\/a>, puedes crear archivos parquet a partir de tus datos Postgres y utilizar servicios como <a href=\"https:\/\/ahana.io\/answers\/query-parquet-using-amazon-athena\/\" target=\"_blank\" rel=\"noopener noreferrer\">AWS Athena<\/a> para leerlos directamente sin necesidad de volver a cargarlos en la base de datos en el futuro.<\/p>\n<p>Instala la biblioteca ParquetJS ejecutando el siguiente comando:<\/p>\n<pre><code class=\"language-bash\">yarn add parquetjs<\/code><\/pre>\n<p>Al crear archivos, necesitas consultar un gran n\u00famero de registros de tus tablas. Almacenar tal cantidad de datos en la memoria de tu aplicaci\u00f3n puede consumir muchos recursos, ser costoso y propenso a errores.<\/p>\n<p>Por lo tanto, tiene sentido utilizar <a href=\"https:\/\/node-postgres.com\/apis\/cursor\" target=\"_blank\" rel=\"noopener noreferrer\">cursores<\/a> para cargar trozos de datos de la base de datos y procesarlos. Instala el m\u00f3dulo <code>cursors<\/code> del paquete <code>node-postgres<\/code> ejecutando el siguiente comando:<\/p>\n<pre><code class=\"language-bash\">yarn add pg-cursor<\/code><\/pre>\n<p>A continuaci\u00f3n, aseg\u00farate de importar ambas bibliotecas en tu archivo <strong>index.js<\/strong>:<\/p>\n<pre><code class=\"language-js\">const Cursor = require('pg-cursor')\nconst parquet = require('parquetjs')<\/code><\/pre>\n<p>Ahora, puedes utilizar el fragmento de c\u00f3digo siguiente para crear archivos de parquet a partir de tu base de datos:<\/p>\n<pre><code class=\"language-js\">app.get('\/archive', async (req, res) =&gt; {\n\n    \/\/ Query all comments through a cursor, reading only 10 at a time\n    \/\/ You can change the query here to meet your requirements, such as archiving records older than at least a month, or only archiving records from inactive users, etc.\n    const queryString = \"SELECT * FROM COMMENTS;\"\n\n    const cursor = client.query(new Cursor(queryString))\n\n    \/\/ Define the schema for the parquet file\n    let schema = new parquet.ParquetSchema({\n        comment_id: { type: 'INT64' },\n        post_id: { type: 'INT64' },\n        user_id: { type: 'INT64' },\n        comment_text: { type: 'UTF8' },\n        timestamp: { type: 'TIMESTAMP_MILLIS' }\n    });\n\n\n\n    \/\/ Open a parquet file writer\n    let writer = await parquet.ParquetWriter.openFile(schema, 'archive\/archive.parquet');\n\n    let rows = await cursor.read(10)\n\n    while (rows.length &gt; 0) {\n\n        for (let i = 0; i &lt; rows.length; i++) {\n            \/\/ Write each row from table to the parquet file\n            await writer.appendRow(rows[i])\n        }\n\n        rows = await cursor.read(10)\n    }\n\n    await writer.close()\n    \n    \/\/ Once the parquet file is generated, you can consider deleting the records from the table at this point to free up some space\n\n    \/\/ Redirect user to the file path to allow them to download the file\n    res.redirect(\"\/archive\/archive.parquet\")\n})<\/code><\/pre>\n<p>A continuaci\u00f3n, a\u00f1ade el siguiente c\u00f3digo al principio de tu archivo <strong>index.js<\/strong> despu\u00e9s de inicializar la aplicaci\u00f3n Express:<\/p>\n<pre><code class=\"language-js\">app.use('\/archive', express.static('archive'))<\/code><\/pre>\n<p>Esto permite que la carpeta <strong>archive<\/strong>\u00a0se sirva est\u00e1ticamente, permiti\u00e9ndote descargar del servidor los archivos de parquet generados.<\/p>\n<p>No olvides crear el directorio <strong>archive<\/strong>\u00a0en el directorio del proyecto para almacenar los ficheros de archivo.<\/p>\n<p>Puedes personalizar a\u00fan m\u00e1s este fragmento de c\u00f3digo para subir autom\u00e1ticamente los archivos de parquet a un <a href=\"https:\/\/sparkbyexamples.com\/spark\/spark-read-write-parquet-file-from-amazon-s3\/\" target=\"_blank\" rel=\"noopener noreferrer\">bucket de AWS S3<\/a> y utilizar trabajos CRON para activar la operaci\u00f3n en una rutina autom\u00e1ticamente.<\/p>\n<h3>5. Limpieza de Datos<\/h3>\n<p>Un prop\u00f3sito com\u00fan para ejecutar operaciones de mantenimiento de bases de datos es limpiar los datos que envejecen o se vuelven irrelevantes con el tiempo. En esta secci\u00f3n se tratan dos casos comunes en los que se realizan limpiezas de datos como parte del mantenimiento.<\/p>\n<p>En realidad, puedes configurar tu propia rutina de limpieza de datos seg\u00fan requieran los modelos de datos de tu aplicaci\u00f3n. Los ejemplos que se dan a continuaci\u00f3n son s\u00f3lo de referencia.<\/p>\n<h4>Borrar Registros por Antig\u00fcedad (\u00daltima Modificaci\u00f3n o \u00daltimo Acceso)<\/h4>\n<p>Limpiar registros en funci\u00f3n de su antig\u00fcedad es relativamente sencillo en comparaci\u00f3n con otras operaciones de esta lista. Puedes escribir una consulta de eliminaci\u00f3n que borre los registros que sean anteriores a una fecha establecida.<\/p>\n<p>Aqu\u00ed tienes un ejemplo para borrar comentarios anteriores al 9 de octubre de 2023:<\/p>\n<pre><code class=\"language-js\">app.get(\"\/clean-by-age\", async (req, res) =&gt; {\n\n    \/\/ Filter and delete all comments that were made on or before 9th October, 2023\n    const result = await client.query(\"DELETE FROM COMMENTS WHERE timestamp &lt; '09-10-2023 00:00:00'\")\n\n    if (result.rowCount &gt; 0) {\n        res.json({message: \"Cleaned up \" + result.rowCount + \" rows successfully!\"})\n    } else {\n        res.json({message: \"Nothing to clean up!\"})\n    }\n})<\/code><\/pre>\n<p>Puedes probarlo enviando una solicitud GET a la ruta <code>\/clean-by-age<\/code>.<\/p>\n<h4>Borrar Registros Bas\u00e1ndose en Condiciones Personalizadas<\/h4>\n<p>Tambi\u00e9n puedes configurar limpiezas basadas en otras condiciones, como eliminar registros que no est\u00e9n vinculados a otros registros activos en el sistema (creando una situaci\u00f3n de <em>orfandad<\/em> ).<\/p>\n<p>Por ejemplo, puedes configurar una operaci\u00f3n de limpieza que busque comentarios vinculados a entradas eliminadas y los elimine, ya que probablemente nunca vuelvan a aparecer en la aplicaci\u00f3n:<\/p>\n<pre><code class=\"language-js\">app.get('\/conditional',  async (req, res) =&gt; {\n\n    \/\/ Filter and delete all comments that are not linked to any active posts\n    const result = await client.query(\"DELETE FROM COMMENTS WHERE post_id NOT IN (SELECT post_id from Posts);\")\n\n    if (result.rowCount &gt; 0) {\n        res.json({message: \"Cleaned up \" + result.rowCount + \" rows successfully!\"})\n    } else {\n        res.json({message: \"Nothing to clean up!\"})\n    }\n})<\/code><\/pre>\n<p>Puedes idear tus propias condiciones espec\u00edficas para tu caso de uso.<\/p>\n<h3>6. Manipulaci\u00f3n de Datos<\/h3>\n<p>Las operaciones de mantenimiento de bases de datos tambi\u00e9n se utilizan para realizar manipulaciones y transformaciones de datos, como censurar lenguaje obsceno o convertir combinaciones de texto en emoji.<\/p>\n<p>A diferencia de la mayor\u00eda de las dem\u00e1s operaciones, es mejor ejecutar estas operaciones cuando se producen actualizaciones de la base de datos (en lugar de ejecutarlas en todas las filas en un momento fijo de la semana o del mes).<\/p>\n<p>En esta secci\u00f3n se enumeran dos de estas operaciones, pero la implementaci\u00f3n para cualquier otra operaci\u00f3n de manipulaci\u00f3n personalizada sigue siendo bastante similar a \u00e9stas.<\/p>\n<h4>Convertir Texto en Emoji<\/h4>\n<p>Puedes considerar convertir combinaciones de texto como \u00ab:)\u00bb y \u00abxD\u00bb en emojis reales para ofrecer una mejor experiencia al usuario y mantener tambi\u00e9n la coherencia de la informaci\u00f3n. Aqu\u00ed tienes un fragmento de c\u00f3digo que te ayudar\u00e1 a hacerlo:<\/p>\n<pre><code class=\"language-js\">app.get(\"\/emoji\", async (req, res) =&gt; {\n    \/\/ Define a list of emojis that need to be converted\n    const emojiMap = {\n        xD: '\ud83d\ude01',\n        ':)': '\ud83d\ude0a',\n        ':-)': '\ud83d\ude04',\n        ':jack_o_lantern:': '\ud83c\udf83',\n        ':ghost:': '\ud83d\udc7b',\n        ':santa:': '\ud83c\udf85',\n        ':christmas_tree:': '\ud83c\udf84',\n        ':gift:': '\ud83c\udf81',\n        ':bell:': '\ud83d\udd14',\n        ':no_bell:': '\ud83d\udd15',\n        ':tanabata_tree:': '\ud83c\udf8b',\n        ':tada:': '\ud83c\udf89',\n        ':confetti_ball:': '\ud83c\udf8a',\n        ':balloon:': '\ud83c\udf88'\n    }\n\n    \/\/ Build the SQL query adding conditional checks for all emojis from the map\n    let queryString = \"SELECT * FROM COMMENTS WHERE\"\n\n    queryString += \" COMMENT_TEXT LIKE '%\" + Object.keys(emojiMap)[0] + \"%' \"\n\n    if (Object.keys(emojiMap).length &gt; 1) {\n        for (let i = 1; i &lt; Object.keys(emojiMap).length; i++) {\n            queryString += \" OR COMMENT_TEXT LIKE '%\" + Object.keys(emojiMap)[i] + \"%' \"\n        }\n    }\n\n    queryString += \";\"\n\n    const result = await client.query(queryString)\n\n    if (result.rowCount === 0) {\n        res.json({message: \"No rows to clean up!\"})\n    } else {\n        for (let i = 0; i &lt; result.rows.length; i++) {\n\n            const currentRow = result.rows[i]\n            let emoji\n\n            \/\/ Identify each row that contains an emoji along with which emoji it contains\n            for (let j = 0; j &lt; Object.keys(emojiMap).length; j++) {\n                if (currentRow.comment_text.includes(Object.keys(emojiMap)[j])) {\n                    emoji = Object.keys(emojiMap)[j]\n                    break\n                }\n            }\n\n            \/\/ Replace the emoji in the text and update the row before moving on to the next row\n            const updateQuery = \"UPDATE COMMENTS SET COMMENT_TEXT = '\" + currentRow.comment_text.replace(emoji, emojiMap[emoji]) + \"' WHERE COMMENT_ID = \" + currentRow.comment_id + \";\"\n\n            await client.query(updateQuery)\n        }\n\n        res.json({message: \"All emojis cleaned up successfully!\"})\n    }\n\n})<\/code><\/pre>\n<p>Este fragmento de c\u00f3digo primero requiere que definas una lista de emojis y sus representaciones textuales. Despu\u00e9s, consulta la base de datos para buscar esas combinaciones textuales y las sustituye por emojis.<\/p>\n<h4>Censura el Lenguaje Obsceno<\/h4>\n<p>Una operaci\u00f3n bastante habitual en las aplicaciones que permiten contenidos generados por los usuarios es censurar cualquier lenguaje indecente. El enfoque aqu\u00ed es similar \u2014 identifica los casos de lenguaje obsceno y sustit\u00fayelos por caracteres asterisco. Puedes utilizar el paquete bad-words (malas-palabras)\u00a0para comprobar y censurar f\u00e1cilmente las blasfemias.<\/p>\n<p>Instala el paquete ejecutando el siguiente comando:<\/p>\n<pre><code class=\"language-bash\">yarn add bad-words<\/code><\/pre>\n<p>A continuaci\u00f3n, inicializa el paquete en tu archivo <strong>index.js<\/strong>:<\/p>\n<pre><code class=\"language-js\">const Filter = require('bad-words');\nfilter = new Filter();<\/code><\/pre>\n<p>Ahora, utiliza el siguiente fragmento de c\u00f3digo para censurar el contenido obsceno en tu tabla de comentarios:<\/p>\n<pre><code class=\"language-js\">app.get('\/obscene', async (req, res) =&gt; {\n\n    \/\/ Query all comments using a cursor, reading only 10 at a time\n    const queryString = \"SELECT * FROM COMMENTS;\"\n\n    const cursor = client.query(new Cursor(queryString))\n\n    let rows = await cursor.read(10)\n\n    const affectedRows = []\n\n    while (rows.length &gt; 0) {\n\n        for (let i = 0; i &lt; rows.length; i++) {\n            \/\/ Check each comment for profane content\n            if (filter.isProfane(rows[i].comment_text)) {\n                affectedRows.push(rows[i])\n            }\n        }\n\n        rows = await cursor.read(10)\n    }\n\n    cursor.close()\n\n    \/\/ Update each comment that has profane content with a censored version of the text\n    for (let i = 0; i &lt; affectedRows.length; i++) {\n        const row = affectedRows[i]\n        const updateQuery = \"UPDATE COMMENTS SET COMMENT_TEXT = '\" + filter.clean(row.comment_text) + \"' WHERE COMMENT_ID = \" + row.comment_id + \";\"\n        await client.query(updateQuery)\n    }\n\n    res.json({message: \"Cleanup complete\"})\n\n})<\/code><\/pre>\n<p>Puedes encontrar el c\u00f3digo completo de este tutorial en <a href=\"https:\/\/github.com\/krharsh17\/node-db-maintenance\" target=\"_blank\" rel=\"noopener noreferrer\">este repositorio de GitHub<\/a>.<\/p>\n<h2>Comprender el Vacuum de PostgreSQL y su Finalidad<\/h2>\n<p>Aparte de configurar rutinas de mantenimiento personalizadas como las comentadas anteriormente, tambi\u00e9n puedes hacer uso de una de las funcionalidades de mantenimiento nativas que ofrece PostgreSQL para garantizar la salud y el rendimiento continuos de tu base de datos: <a href=\"https:\/\/www.postgresql.org\/docs\/current\/routine-vacuuming.html\">el proceso Vacuum<\/a>.<\/p>\n<p>El proceso Vacuum ayuda a optimizar el rendimiento de la base de datos y a recuperar espacio en disco. PostgreSQL ejecuta operaciones de vacuum de manera programada mediante su daemon de auto-vacuum, pero tambi\u00e9n puedes activarlo manualmente si es necesario. A continuaci\u00f3n, se presentan algunas maneras en las que el vacuuming frecuente es beneficioso:<\/p>\n<ul>\n<li><strong>Recuperar espacio de disco bloqueado<\/strong>: Uno de los principales objetivos de Vacuum es recuperar el espacio de disco bloqueado en la base de datos. Como los datos se insertan, actualizan y eliminan constantemente, PostgreSQL puede llenarse de filas \u00abmuertas\u00bb u obsoletas que siguen ocupando espacio en el disco. Vacuum identifica y elimina estas filas muertas, dejando el espacio disponible para nuevos datos. Sin Vacuum, el espacio en disco se agotar\u00eda gradualmente, lo que podr\u00eda provocar una degradaci\u00f3n del rendimiento e incluso fallos del sistema.<\/li>\n<li><strong>Actualizar las M\u00e9tricas del Planificador de Consultas<\/strong>: Vacuuming tambi\u00e9n ayuda a PostgreSQL a mantener actualizadas las estad\u00edsticas y m\u00e9tricas utilizadas por su planificador de consultas. El planificador de consultas depende de una distribuci\u00f3n precisa de los datos y de la informaci\u00f3n estad\u00edstica para generar planes de ejecuci\u00f3n eficientes. Al ejecutar regularmente Vacuum, PostgreSQL se asegura de que estas m\u00e9tricas est\u00e1n actualizadas, lo que le permite tomar mejores decisiones sobre c\u00f3mo recuperar datos y optimizar las consultas.<\/li>\n<li><strong>Actualizar el Mapa de Visibilidad<\/strong>: El Mapa de Visibilidad es otro aspecto crucial del proceso Vacuum de PostgreSQL. Ayuda a identificar qu\u00e9 bloques de datos de una tabla son totalmente visibles para todas las transacciones, lo que permite a Vacuum seleccionar s\u00f3lo los bloques de datos necesarios para su limpieza. Esto aumenta la eficacia del proceso Vacuum al minimizar las operaciones de E\/S innecesarias, que ser\u00edan costosas y llevar\u00edan mucho tiempo.<\/li>\n<li><strong>Prevenci\u00f3n de Fallos por Envoltura de ID de Transacci\u00f3n<\/strong>: Vacuum tambi\u00e9n desempe\u00f1a un papel fundamental en la prevenci\u00f3n de fallos de envoltura del ID de transacci\u00f3n. PostgreSQL utiliza un contador de ID de transacci\u00f3n de 32 bits, que puede provocar un wraparound cuando alcanza su valor m\u00e1ximo. Vacuum marca las transacciones antiguas como \u00abcongeladas\u00bb, evitando que el contador de ID se envuelva y provoque la corrupci\u00f3n de los datos. Descuidar este aspecto podr\u00eda provocar fallos catastr\u00f3ficos en la base de datos.<\/li>\n<\/ul>\n<p>Como ya se ha dicho, PostgreSQL ofrece dos opciones para ejecutar Vacuum: <a href=\"https:\/\/www.postgresql.org\/docs\/current\/routine-vacuuming.html#AUTOVACUUM\" target=\"_blank\" rel=\"noopener noreferrer\">Autovacuum<\/a> y <a href=\"https:\/\/www.postgresql.org\/docs\/current\/sql-vacuum.html\" target=\"_blank\" rel=\"noopener noreferrer\">Vacuum Manual<\/a>.<\/p>\n<p>Autovacuum es la opci\u00f3n recomendada para la mayor\u00eda de los escenarios, ya que gestiona autom\u00e1ticamente el proceso de Vacuum bas\u00e1ndose en ajustes predefinidos y en la actividad de la base de datos. El Vacuum\u00a0Manual, en cambio, proporciona m\u00e1s control, pero requiere un conocimiento m\u00e1s profundo del mantenimiento de la base de datos.<\/p>\n<p>La decisi\u00f3n entre ambos depende de factores como el tama\u00f1o de la base de datos, la carga de trabajo y los recursos disponibles. Las bases de datos de tama\u00f1o peque\u00f1o o mediano pueden confiar a menudo en el Vacuum Autom\u00e1tico, mientras que las bases de datos m\u00e1s grandes o complejas pueden requerir la intervenci\u00f3n manual.<\/p>\n<h2>Resumen<\/h2>\n<p>El mantenimiento de las bases de datos no es s\u00f3lo una cuesti\u00f3n de limpieza rutinaria; es la base de una aplicaci\u00f3n sana y eficaz. Optimizando, limpiando y organizando tus datos con regularidad, te aseguras de que tu base de datos PostgreSQL siga ofreciendo el m\u00e1ximo rendimiento, se mantenga libre de corrupci\u00f3n y funcione con eficacia, incluso cuando tu aplicaci\u00f3n se ampl\u00ede.<\/p>\n<p>En esta completa gu\u00eda, exploramos la importancia cr\u00edtica de establecer planes de mantenimiento de bases de datos bien estructurados para PostgreSQL cuando se trabaja con Node.js y Express.<\/p>\n<p><em>\u00bfHemos pasado por alto alguna operaci\u00f3n rutinaria de mantenimiento de bases de datos que hayas implementado para tu base de datos? \u00bfO conoces una forma mejor de poner en pr\u00e1ctica alguna de las comentadas anteriormente? \u00a1No dudes en hac\u00e9rnoslo saber en los comentarios!<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A medida que evoluciona el desarrollo de aplicaciones, las bases de datos se erigen en el n\u00facleo de la mayor\u00eda de las aplicaciones, almacenando y gestionando &#8230;<\/p>\n","protected":false},"author":238,"featured_media":71793,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kinsta_gated_content":false,"_kinsta_gated_content_redirect":"","footnotes":""},"tags":[],"topic":[1329,1311,1319],"class_list":["post-71792","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","topic-consejos-tecnologicos","topic-node-js","topic-postgresql"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v24.6 (Yoast SEO v24.6) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Configuraci\u00f3n del mantenimiento de bases de datos PostgreSQL en Node<\/title>\n<meta name=\"description\" content=\"Aprende a mantener sin problemas bases de datos PostgreSQL en Node.js con nuestra completa gu\u00eda. \u00a1Eleva tu juego de gesti\u00f3n de bases de datos sin esfuerzo!\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Configuraci\u00f3n de Planes de Mantenimiento de Bases de Datos para PostgreSQL en Node.js\" \/>\n<meta property=\"og:description\" content=\"Aprende a mantener sin problemas bases de datos PostgreSQL en Node.js con nuestra completa gu\u00eda. \u00a1Eleva tu juego de gesti\u00f3n de bases de datos sin esfuerzo!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/\" \/>\n<meta property=\"og:site_name\" content=\"Kinsta\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/kinsta.es\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-11-23T12:27:33+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-30T12:39:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1460\" \/>\n\t<meta property=\"og:image:height\" content=\"730\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Kumar Harsh\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:description\" content=\"Aprende a mantener sin problemas bases de datos PostgreSQL en Node.js con nuestra completa gu\u00eda. \u00a1Eleva tu juego de gesti\u00f3n de bases de datos sin esfuerzo!\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg\" \/>\n<meta name=\"twitter:creator\" content=\"@Kinsta_ES\" \/>\n<meta name=\"twitter:site\" content=\"@Kinsta_ES\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kumar Harsh\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/\"},\"author\":{\"name\":\"Kumar Harsh\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9\"},\"headline\":\"Configuraci\u00f3n de Planes de Mantenimiento de Bases de Datos para PostgreSQL en Node.js\",\"datePublished\":\"2023-11-23T12:27:33+00:00\",\"dateModified\":\"2023-11-30T12:39:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/\"},\"wordCount\":3631,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/es\/#organization\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg\",\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/\",\"url\":\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/\",\"name\":\"Configuraci\u00f3n del mantenimiento de bases de datos PostgreSQL en Node\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/es\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg\",\"datePublished\":\"2023-11-23T12:27:33+00:00\",\"dateModified\":\"2023-11-30T12:39:18+00:00\",\"description\":\"Aprende a mantener sin problemas bases de datos PostgreSQL en Node.js con nuestra completa gu\u00eda. \u00a1Eleva tu juego de gesti\u00f3n de bases de datos sin esfuerzo!\",\"breadcrumb\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#primaryimage\",\"url\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg\",\"contentUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg\",\"width\":1460,\"height\":730},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kinsta.com\/es\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"PostgreSQL\",\"item\":\"https:\/\/kinsta.com\/es\/secciones\/postgresql\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Configuraci\u00f3n de Planes de Mantenimiento de Bases de Datos para PostgreSQL en Node.js\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kinsta.com\/es\/#website\",\"url\":\"https:\/\/kinsta.com\/es\/\",\"name\":\"Kinsta\u00ae\",\"description\":\"Soluciones de alojamiento premium, r\u00e1pidas y seguras\",\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/es\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kinsta.com\/es\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kinsta.com\/es\/#organization\",\"name\":\"Kinsta\",\"url\":\"https:\/\/kinsta.com\/es\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg\",\"width\":500,\"height\":500,\"caption\":\"Kinsta\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/kinsta.es\/\",\"https:\/\/x.com\/Kinsta_ES\",\"https:\/\/www.instagram.com\/kinstahosting\/\",\"https:\/\/www.linkedin.com\/company\/kinsta\/\",\"https:\/\/www.pinterest.com\/kinstahosting\/\",\"https:\/\/www.youtube.com\/c\/Kinsta\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9\",\"name\":\"Kumar Harsh\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/de2d8d6273bdcc3dfa2f8270428f95b2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/de2d8d6273bdcc3dfa2f8270428f95b2?s=96&d=mm&r=g\",\"caption\":\"Kumar Harsh\"},\"description\":\"Kumar is a software developer and a technical author based in India. He specializes in JavaScript and DevOps. You can learn more about his work on his website.\",\"sameAs\":[\"https:\/\/kumarharsh.me\"],\"url\":\"https:\/\/kinsta.com\/es\/blog\/author\/kumarharsh\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Configuraci\u00f3n del mantenimiento de bases de datos PostgreSQL en Node","description":"Aprende a mantener sin problemas bases de datos PostgreSQL en Node.js con nuestra completa gu\u00eda. \u00a1Eleva tu juego de gesti\u00f3n de bases de datos sin esfuerzo!","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/","og_locale":"es_ES","og_type":"article","og_title":"Configuraci\u00f3n de Planes de Mantenimiento de Bases de Datos para PostgreSQL en Node.js","og_description":"Aprende a mantener sin problemas bases de datos PostgreSQL en Node.js con nuestra completa gu\u00eda. \u00a1Eleva tu juego de gesti\u00f3n de bases de datos sin esfuerzo!","og_url":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/","og_site_name":"Kinsta\u00ae","article_publisher":"https:\/\/www.facebook.com\/kinsta.es\/","article_published_time":"2023-11-23T12:27:33+00:00","article_modified_time":"2023-11-30T12:39:18+00:00","og_image":[{"width":1460,"height":730,"url":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg","type":"image\/jpeg"}],"author":"Kumar Harsh","twitter_card":"summary_large_image","twitter_description":"Aprende a mantener sin problemas bases de datos PostgreSQL en Node.js con nuestra completa gu\u00eda. \u00a1Eleva tu juego de gesti\u00f3n de bases de datos sin esfuerzo!","twitter_image":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg","twitter_creator":"@Kinsta_ES","twitter_site":"@Kinsta_ES","twitter_misc":{"Escrito por":"Kumar Harsh","Tiempo de lectura":"20 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#article","isPartOf":{"@id":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/"},"author":{"name":"Kumar Harsh","@id":"https:\/\/kinsta.com\/es\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9"},"headline":"Configuraci\u00f3n de Planes de Mantenimiento de Bases de Datos para PostgreSQL en Node.js","datePublished":"2023-11-23T12:27:33+00:00","dateModified":"2023-11-30T12:39:18+00:00","mainEntityOfPage":{"@id":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/"},"wordCount":3631,"commentCount":0,"publisher":{"@id":"https:\/\/kinsta.com\/es\/#organization"},"image":{"@id":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg","inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/","url":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/","name":"Configuraci\u00f3n del mantenimiento de bases de datos PostgreSQL en Node","isPartOf":{"@id":"https:\/\/kinsta.com\/es\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#primaryimage"},"image":{"@id":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg","datePublished":"2023-11-23T12:27:33+00:00","dateModified":"2023-11-30T12:39:18+00:00","description":"Aprende a mantener sin problemas bases de datos PostgreSQL en Node.js con nuestra completa gu\u00eda. \u00a1Eleva tu juego de gesti\u00f3n de bases de datos sin esfuerzo!","breadcrumb":{"@id":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#primaryimage","url":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg","contentUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/11\/database-maintenance-plan.jpg","width":1460,"height":730},{"@type":"BreadcrumbList","@id":"https:\/\/kinsta.com\/es\/blog\/plan-de-mantenimiento-de-la-base-de-datos\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kinsta.com\/es\/"},{"@type":"ListItem","position":2,"name":"PostgreSQL","item":"https:\/\/kinsta.com\/es\/secciones\/postgresql\/"},{"@type":"ListItem","position":3,"name":"Configuraci\u00f3n de Planes de Mantenimiento de Bases de Datos para PostgreSQL en Node.js"}]},{"@type":"WebSite","@id":"https:\/\/kinsta.com\/es\/#website","url":"https:\/\/kinsta.com\/es\/","name":"Kinsta\u00ae","description":"Soluciones de alojamiento premium, r\u00e1pidas y seguras","publisher":{"@id":"https:\/\/kinsta.com\/es\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kinsta.com\/es\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/kinsta.com\/es\/#organization","name":"Kinsta","url":"https:\/\/kinsta.com\/es\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/","url":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg","contentUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg","width":500,"height":500,"caption":"Kinsta"},"image":{"@id":"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/kinsta.es\/","https:\/\/x.com\/Kinsta_ES","https:\/\/www.instagram.com\/kinstahosting\/","https:\/\/www.linkedin.com\/company\/kinsta\/","https:\/\/www.pinterest.com\/kinstahosting\/","https:\/\/www.youtube.com\/c\/Kinsta"]},{"@type":"Person","@id":"https:\/\/kinsta.com\/es\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9","name":"Kumar Harsh","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/kinsta.com\/es\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/de2d8d6273bdcc3dfa2f8270428f95b2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/de2d8d6273bdcc3dfa2f8270428f95b2?s=96&d=mm&r=g","caption":"Kumar Harsh"},"description":"Kumar is a software developer and a technical author based in India. He specializes in JavaScript and DevOps. You can learn more about his work on his website.","sameAs":["https:\/\/kumarharsh.me"],"url":"https:\/\/kinsta.com\/es\/blog\/author\/kumarharsh\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts\/71792","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/users\/238"}],"replies":[{"embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/comments?post=71792"}],"version-history":[{"count":6,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts\/71792\/revisions"}],"predecessor-version":[{"id":72114,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts\/71792\/revisions\/72114"}],"alternate":[{"embeddable":true,"hreflang":"en","title":"English","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/71792\/translations\/en"},{"embeddable":true,"hreflang":"it","title":"Italian","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/71792\/translations\/it"},{"embeddable":true,"hreflang":"pt","title":"Portuguese","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/71792\/translations\/pt"},{"embeddable":true,"hreflang":"fr","title":"French","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/71792\/translations\/fr"},{"embeddable":true,"hreflang":"de","title":"German","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/71792\/translations\/de"},{"embeddable":true,"hreflang":"ja","title":"Japanese","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/71792\/translations\/jp"},{"embeddable":true,"hreflang":"es","title":"Spanish","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/71792\/translations\/es"},{"href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/71792\/tree"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/media\/71793"}],"wp:attachment":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/media?parent=71792"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/tags?post=71792"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/topic?post=71792"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}