{"id":74710,"date":"2023-11-23T13:28:39","date_gmt":"2023-11-23T12:28:39","guid":{"rendered":"https:\/\/kinsta.com\/it\/?p=74710&#038;preview=true&#038;preview_id=74710"},"modified":"2023-11-30T13:27:16","modified_gmt":"2023-11-30T12:27:16","slug":"piano-manutenzione-database","status":"publish","type":"post","link":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/","title":{"rendered":"Come impostare dei piani di manutenzione del database per PostgreSQL su Node.js"},"content":{"rendered":"<p>Con l&#8217;evoluzione dello sviluppo delle app, i database rappresentano il fulcro della maggior parte delle applicazioni, in quanto immagazzinano e gestiscono dati fondamentali per le aziende digitali. Poich\u00e9 questi dati crescono e diventano sempre pi\u00f9 complessi, garantire l&#8217;efficienza del database \u00e8 fondamentale per soddisfare le esigenze di un&#8217;applicazione.<\/p>\n<p>\u00c8 qui che entra in gioco il concetto di manutenzione del database. La manutenzione del database comprende attivit\u00e0 come la pulizia, il backup e l&#8217;ottimizzazione degli indici per aumentare le prestazioni.<\/p>\n<p>Questo articolo offre preziose informazioni sui trigger di manutenzione e presenta istruzioni pratiche per la loro configurazione. Spiega il processo di implementazione di varie attivit\u00e0 di manutenzione del database come il backup dei dati, la ricostruzione degli indici, l&#8217;archiviazione e la pulizia dei dati utilizzando <a href=\"https:\/\/kinsta.com\/it\/argomenti\/postgresql\/\">PostgreSQL<\/a>, integrato con un trigger API in un&#8217;applicazione <a href=\"https:\/\/kinsta.com\/it\/argomenti\/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>Capire i trigger<\/h2>\n<p>Prima di creare operazioni di manutenzione per il proprio database, \u00e8 importante capire i vari modi in cui possono essere attivate. Ogni trigger serve a scopi diversi per facilitare le attivit\u00e0 di manutenzione. I tre trigger principali comunemente utilizzati sono:<\/p>\n<ul>\n<li><strong>Manuale, basato su API<\/strong>: questo trigger permette di eseguire operazioni una tantum utilizzando una chiamata API. \u00c8 utile in situazioni come il ripristino del backup di un database o la ricostruzione degli indici quando le prestazioni calano improvvisamente.<\/li>\n<li><strong>Pianificato (come CRON)<\/strong>: questo trigger permette di automatizzare le attivit\u00e0 di manutenzione programmata durante i periodi di scarso traffico di utenti. \u00c8 ideale per eseguire operazioni ad alta intensit\u00e0 di risorse come l&#8217;archiviazione e la pulizia. Si possono utilizzare pacchetti come <a href=\"https:\/\/www.npmjs.com\/package\/node-schedule\" target=\"_blank\" rel=\"noopener noreferrer\">node-schedule<\/a> per impostare pianificazioni in Node.js che attivano automaticamente le operazioni quando necessario.<\/li>\n<li><strong>Notifiche del database<\/strong>: questo trigger permette di eseguire operazioni di manutenzione in risposta alle modifiche del database. Ad esempio, quando un utente pubblica un commento su una piattaforma, i dati salvati possono attivare istantaneamente i controlli per caratteri irregolari, linguaggio offensivo o le emoji. L&#8217;implementazione di questa funzionalit\u00e0 in Node.js \u00e8 possibile utilizzando pacchetti come <a href=\"https:\/\/github.com\/andywer\/pg-listen\" target=\"_blank\" rel=\"noopener noreferrer\">pg-listen<\/a>.<\/li>\n<\/ul>\n<h2>Prerequisiti<\/h2>\n<p>Per seguire questa guida, \u00e8 necessario disporre dei seguenti strumenti sul proprio computer locale:<\/p>\n<ul>\n<li><a href=\"https:\/\/kinsta.com\/it\/blog\/installare-git\/\">Git<\/a>: per gestire il controllo di versione del codice sorgente dell&#8217;applicazione<\/li>\n<li><a href=\"https:\/\/kinsta.com\/it\/blog\/come-installare-node-js\/\">Node.js<\/a>: per costruire l&#8217;applicazione backend<\/li>\n<li><a href=\"https:\/\/www.postgresql.org\/docs\/current\/app-psql.html\" target=\"_blank\" rel=\"noopener noreferrer\">psql<\/a>: per interagire con il database PostgreSQL remoto utilizzando il terminale<\/li>\n<li><a href=\"https:\/\/www.pgadmin.org\/download\/\" target=\"_blank\" rel=\"noopener noreferrer\">PGAdmin<\/a> (opzionale): per interagire con il database PostgreSQL remoto utilizzando un&#8217;interfaccia grafica (GUI).<\/li>\n<\/ul>\n<h3>Creare e ospitare un&#8217;applicazione Node.js<\/h3>\n<p>Creiamo un progetto Node.js, effettuiamo il commit su GitHub e impostiamo una pipeline di auto-deploy su Kinsta. Dovremo anche creare un <a href=\"https:\/\/sevalla.com\/database-hosting\/\">database PostgreSQL su Kinsta<\/a> per testare le routine di manutenzione.<\/p>\n<p>Iniziamo creando una nuova directory sul nostro sistema locale con il seguente comando:<\/p>\n<pre><code class=\"language-bash\">mkdir node-db-maintenance<\/code><\/pre>\n<p>Quindi, entriamo nella cartella appena creata ed eseguiamo il comando qui sotto per creare un nuovo progetto:<\/p>\n<pre><code class=\"language-bash\">cd node-db-maintenance\nyarn init -y # or npm init -y<\/code><\/pre>\n<p>Questo inizializza un progetto Node.js con la configurazione predefinita. Ora possiamo installare le dipendenze necessarie eseguendo il comando:<\/p>\n<pre><code class=\"language-bash\">yarn add express pg nodemon dotenv<\/code><\/pre>\n<p>Ecco una rapida descrizione di ogni pacchetto:<\/p>\n<ul>\n<li><code>express<\/code>: permette di creare un&#8217;API REST basata su Express.<\/li>\n<li><code>pg<\/code>: permette di interagire con un database PostgreSQL attraverso l&#8217;applicazione Node.js.<\/li>\n<li><code>nodemon<\/code>: consente alla build dev di essere aggiornata durante lo sviluppo dell&#8217;applicazione, liberando dalla necessit\u00e0 costante di fermare e avviare l&#8217;applicazione ogni volta che si apporta una modifica.<\/li>\n<li><code>dotenv<\/code>: permette di caricare le variabili d&#8217;ambiente da un file <strong>.env<\/strong> nell&#8217;oggetto <code>process.env<\/code>.<\/li>\n<\/ul>\n<p>Quindi, aggiungiamo i seguenti script nel file <strong>package.json<\/strong> in modo da poter avviare facilmente il server dev ed eseguirlo anche in produzione:<\/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>Ora possiamo creare un file <strong>index.js<\/strong> che contiene il codice sorgente dell&#8217;applicazione. Incolliamo il seguente codice nel file:<\/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>Questo codice inizializza un server <a href=\"https:\/\/kinsta.com\/it\/blog\/cos-e-express-js\/\">Express<\/a> e configura le variabili d&#8217;ambiente utilizzando il pacchetto <code>dotenv<\/code> se non \u00e8 in modalit\u00e0 di produzione. Inoltre, imposta una route <code>\/health<\/code> che restituisce un oggetto JSON <code>{status: \"UP\"}<\/code>. Infine, avvia l&#8217;applicazione utilizzando la funzione <code>app.listen()<\/code> per ascoltare sulla porta specificata, con l&#8217;impostazione predefinita di <code>3000<\/code> se non viene fornita alcuna porta tramite la variabile d&#8217;ambiente.<\/p>\n<p>Ora che abbiamo un&#8217;applicazione di base pronta, inizializziamo un nuovo repository git con il nostro provider git preferito (<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>) e inviamo il codice. Kinsta supporta il deploy delle applicazioni da tutti questi provider git. Per questo articolo, usiamo GitHub.<\/p>\n<p>Quando il repository \u00e8 pronto, seguiamo questi passaggi per distribuire l&#8217;applicazione su Kinsta:<\/p>\n<ol>\n<li>Accediamo o creiamo un account per visualizzare la dashboard <a href=\"https:\/\/my.kinsta.com\/?lang=it\">MyKinsta<\/a>.<\/li>\n<li>Autorizziamo Kinsta con il provider Git.<\/li>\n<li>Nella barra laterale di sinistra, clicchiamo su <strong>Applicazioni<\/strong> e poi su <strong>Aggiungi applicazione<\/strong>.<\/li>\n<li>Selezioniamo il repository e il branch da cui desideriamo effettuare il deploy.<\/li>\n<li>Selezioniamo uno dei data center disponibili dalla lista delle 27 opzioni. Kinsta rileva automaticamente le impostazioni di build delle applicazioni tramite <a href=\"https:\/\/kinsta.com\/it\/changelog\/nixpacks\/\">Nixpacks<\/a>.<\/li>\n<li>Scegliamo le risorse dell&#8217;applicazione, come la RAM e lo spazio su disco.<\/li>\n<li>Clicchiamo su <strong>Crea applicazione<\/strong>.<\/li>\n<\/ol>\n<p>Una volta completata la distribuzione, copiamo il link dell&#8217;applicazione distribuita e navighiamo su <code>\/health<\/code>. Dovremmo vedere il seguente JSON nel browser:<\/p>\n<pre><code class=\"language-js\">{status: \"UP\"}<\/code><\/pre>\n<p>Questo indica che l&#8217;applicazione \u00e8 stata configurata correttamente.<\/p>\n<h3>Impostazione di un&#8217;istanza PostgreSQL su Kinsta<\/h3>\n<p>Kinsta offre un&#8217;interfaccia semplice per fornire istanze di database. Iniziamo creando un nuovo <a href=\"https:\/\/kinsta.com\/it\/registrazione\/\">account Kinsta<\/a> se non ne abbiamo gi\u00e0 uno. Poi, seguiamo questi passaggi:<\/p>\n<ol>\n<li>Accediamo alla dashboard MyKinsta.<\/li>\n<li>Nella barra laterale di sinistra, clicchiamo su <strong>Database<\/strong> e poi su <strong>Aggiungi database<\/strong>.<\/li>\n<li>Selezioniamo <strong>PostgreSQL<\/strong> come tipo di database e scegliamo la versione che preferiamo. Scegliamo un nome per il database e modifichiamo il nome utente e la password se lo desideriamo.<\/li>\n<li>Selezioniamo un data center dalla lista di 27 opzioni.<\/li>\n<li>Scegliamo le dimensioni del database.<\/li>\n<li>Clicchiamo su <strong>Crea database<\/strong>.<\/li>\n<\/ol>\n<p>Una volta creato il database, assicuriamoci di recuperare l&#8217;host, la porta, il nome utente e la password del database.<\/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 schermata mostra l'hostname esterno, la porta, il nome utente, la password, il nome del database e una stringa di connessione esterna per il database creato su Kinsta.\" width=\"1024\" height=\"435\"><figcaption id=\"caption-attachment-168402\" class=\"wp-caption-text\">Credenziali del database generate da Kinsta<\/figcaption><\/figure>\n<p>Potremo quindi inserire questi valori nella CLI psql (o nella GUI PGAdmin) per gestire il database. Per testare il codice a livello locale, creiamo un file <strong>.env<\/strong> nella directory principale del progetto e inseriamo i seguenti segreti:<\/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>Quando effettuiamo il deploy su Kinsta, dobbiamo aggiungere questi valori come <a href=\"https:\/\/docs.sevalla.com\/applications\/overviewenvironment-variables\">variabili d&#8217;ambiente<\/a> al deploy dell&#8217;applicazione.<\/p>\n<p>Per prepararci alle operazioni sul database, scarichiamo ed eseguiamo <a href=\"https:\/\/github.com\/krharsh17\/node-db-maintenance\/blob\/main\/test-data.sql\" target=\"_blank\" rel=\"noopener noreferrer\">questo script SQL<\/a> per creare tabelle (utenti, post, commenti) e inserire dati di esempio. Usiamo il comando qui sotto, sostituendo i placeholder con le nostre specifiche, per aggiungere i dati al database PostgreSQL appena creato:<\/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>Assicuriamoci di inserire il nome e il percorso esatto del file nel comando qui sopra. L&#8217;esecuzione di questo comando richiede l&#8217;inserimento della password del database per l&#8217;autorizzazione.<\/p>\n<p>Una volta completata l&#8217;esecuzione di questo comando, saremo pronti a iniziare a scrivere le operazioni di manutenzione del database. Non esitate a inviare il codice al vostro repository Git al termine di ogni operazione per vederlo in azione sulla piattaforma Kinsta.<\/p>\n<h2>Scrivere le routine di manutenzione<\/h2>\n<p>Questa sezione analizza diverse operazioni comunemente utilizzate per la manutenzione dei database PostgreSQL.<\/p>\n<h3>1. Creare backup<\/h3>\n<p>Eseguire regolarmente il backup dei database \u00e8 un&#8217;operazione comune ed essenziale. Si tratta di creare una copia dell&#8217;intero contenuto del database, che viene conservata in un luogo sicuro. Questi backup sono fondamentali per ripristinare i dati in caso di perdita accidentale o di errori che ne compromettono l&#8217;integrit\u00e0.<\/p>\n<p>Anche se <a href=\"https:\/\/docs.sevalla.com\/databases\/backups\">piattaforme come Kinsta offrono backup automatici<\/a> come parte dei loro servizi, \u00e8 importante sapere come impostare una routine di backup personalizzata, se necessario.<\/p>\n<p>PostgreSQL offre lo strumento <a href=\"https:\/\/www.postgresql.org\/docs\/current\/app-pgdump.html\" target=\"_blank\" rel=\"noopener noreferrer\">pg_dump<\/a> per creare backup dei database. Tuttavia, deve essere eseguito direttamente dalla riga di comando e non esiste un pacchetto npm per questo strumento. Quindi, \u00e8 necessario utilizzare il pacchetto <a href=\"https:\/\/www.npmjs.com\/package\/@getvim\/execute\" target=\"_blank\" rel=\"noopener noreferrer\">@getvim\/execute<\/a> per eseguire il comando <code>pg_dump<\/code> nell&#8217;ambiente locale dell&#8217;applicazione Node.<\/p>\n<p>Installiamo il pacchetto eseguendo il comando:<\/p>\n<pre><code class=\"language-bash\">yarn add @getvim\/execute<\/code><\/pre>\n<p>Successivamente, importiamo il pacchetto nel file <strong>index.js<\/strong> aggiungendo questa riga di codice all&#8217;inizio:<\/p>\n<pre><code class=\"language-js\">const {execute} = require('@getvim\/execute');<\/code><\/pre>\n<p>I backup vengono generati come file sul filesystem locale dell&#8217;applicazione Node. Per questo motivo, \u00e8 meglio creare una cartella dedicata con il nome <strong>backup<\/strong> nella directory principale del progetto.<\/p>\n<p>Ora possiamo utilizzare il seguente percorso per generare e scaricare i backup del database quando necessario:<\/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>Inoltre, dovremo aggiungere la seguente riga all&#8217;inizio del file <strong>index.js<\/strong> dopo l&#8217;inizializzazione dell&#8217;applicazione Express:<\/p>\n<pre><code class=\"language-js\">app.use('\/backup', express.static('backup'))<\/code><\/pre>\n<p>Questo permette alla cartella <strong>backup<\/strong> di essere servita staticamente utilizzando la funzione middleware <code>express.static<\/code>, consentendo all&#8217;utente di scaricare i file di backup generati dall&#8217;applicazione Node.<\/p>\n<aside role=\"note\" class=\"wp-block-kinsta-notice is-style-info\">\n            <h3>Info<\/h3>\n        <p>Se riscontrate un errore <code>server version mismatch<\/code> con PostgreSQL, significa che la versione del database \u00e8 diversa da quella dello strumento locale <code>pg_dump<\/code>. \u00c8 possibile risolvere il problema controllando la versione di <code>pg_dump<\/code> e aggiornando lo strumento o il database.<\/p>\n<\/aside>\n\n<h3>2. Ripristino da un backup<\/h3>\n<p>Postgres consente di ripristinare da un backup utilizzando lo strumento da linea di comando <code>pg_restore<\/code>. Tuttavia, \u00e8 necessario usarlo tramite il pacchetto <code>execute<\/code>, in modo simile a come abbiamo usato il comando <code>pg_dump<\/code>. Ecco il codice della route:<\/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>Il frammento di codice qui sopra cerca innanzitutto i file memorizzati nella directory di <strong>backup<\/strong> locale. Poi li ordina in base alla data di creazione per trovare il file di backup pi\u00f9 recente. Infine, utilizza il pacchetto <code>execute<\/code> per ripristinare il file di backup scelto.<\/p>\n<p>Assicuriamoci di aggiungere le seguenti importazioni al file <strong>index.js<\/strong> in modo da importare i moduli necessari per accedere al filesystem locale e permettere alla funzione di essere eseguita correttamente:<\/p>\n<pre><code class=\"language-js\">const fs = require('fs')\nconst path = require('path')<\/code><\/pre>\n<h3>3. Ricostruire un indice<\/h3>\n<p>Gli indici delle tabelle Postgres a volte si corrompono e le prestazioni del database si riducono. Ci\u00f2 pu\u00f2 essere dovuto a bug o errori del software. A volte, gli indici possono anche gonfiarsi a causa di un numero eccessivo di pagine vuote o quasi vuote.<\/p>\n<p>In questi casi, sar\u00e0 neccesario ricostruire l&#8217;indice per assicurarci di ottenere le migliori prestazioni dall&#8217;istanza Postgres.<\/p>\n<p>A questo scopo, Postgres offre il comando <a href=\"https:\/\/www.postgresql.org\/docs\/current\/sql-reindex.html\" target=\"_blank\" rel=\"noopener noreferrer\">REINDEX<\/a>. Possiamo utilizzare il pacchetto <a href=\"https:\/\/node-postgres.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">node-postgres<\/a> per eseguire questo comando (e anche per eseguire altre operazioni in seguito), quindi installiamolo eseguendo prima il seguente comando:<\/p>\n<pre><code class=\"language-bash\">yarn add pg<\/code><\/pre>\n<p>Quindi, aggiungiamo le seguenti righe all&#8217;inizio del file <strong>index.js<\/strong> sotto le importazioni per inizializzare correttamente la connessione al database:<\/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>L&#8217;implementazione di questa operazione \u00e8 piuttosto semplice:<\/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>Il comando mostrato sopra reindicizza l&#8217;intera tabella Utenti. Possiamo personalizzare il comando in base alle esigenze per ricostruire un indice particolare o per reindicizzare l&#8217;intero database.<\/p>\n<h3>4. Archiviazione e pulizia dei dati<\/h3>\n<p>Per i database che diventano grandi con il passare del tempo (e i cui dati storici vengono consultati raramente), potrebbe essere utile impostare delle routine che scaricano i vecchi dati in un data lake dove possono essere archiviati ed elaborati pi\u00f9 comodamente.<\/p>\n<p>I file Parquet sono uno standard comune per l&#8217;archiviazione e il trasferimento dei dati in molti data lake. Utilizzando la libreria <a href=\"https:\/\/www.npmjs.com\/package\/parquetjs\" target=\"_blank\" rel=\"noopener noreferrer\">ParquetJS<\/a>, si possono creare file parquet dai dati Postgres e utilizzare servizi come <a href=\"https:\/\/ahana.io\/answers\/query-parquet-using-amazon-athena\/\" target=\"_blank\" rel=\"noopener noreferrer\">AWS Athena<\/a> per leggerli direttamente senza doverli caricare nuovamente nel database in futuro.<\/p>\n<p>Installiamo la libreria ParquetJS eseguendo questo comando:<\/p>\n<pre><code class=\"language-bash\">yarn add parquetjs<\/code><\/pre>\n<p>Quando creiamo degli archivi, dobbiamo interrogare un gran numero di record dalle tabelle. Memorizzare una tale quantit\u00e0 di dati nella memoria dell&#8217;applicazione pu\u00f2 essere dispendioso in termini di risorse, costoso e soggetto a errori.<\/p>\n<p>Per questo motivo, ha senso utilizzare dei <a href=\"https:\/\/node-postgres.com\/apis\/cursor\" target=\"_blank\" rel=\"noopener noreferrer\">cursori<\/a> per caricare pezzi di dati dal database ed elaborarli. Installiamo il modulo <code>cursors<\/code> del pacchetto <code>node-postgres<\/code> eseguendo il comando:<\/p>\n<pre><code class=\"language-bash\">yarn add pg-cursor<\/code><\/pre>\n<p>Successivamente, assicuriamoci di importare entrambe le librerie nel file <strong>index.js<\/strong>:<\/p>\n<pre><code class=\"language-js\">const Cursor = require('pg-cursor')\nconst parquet = require('parquetjs')<\/code><\/pre>\n<p>Ora possiamo usare lo snippet di codice qui sotto per creare file di parquet dal database:<\/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>Quindi, aggiungiamo il seguente codice all&#8217;inizio del file <strong>index.js<\/strong> dopo che l&#8217;applicazione Express \u00e8 stata inizializzata:<\/p>\n<pre><code class=\"language-js\">app.use('\/archive', express.static('archive'))<\/code><\/pre>\n<p>Questo permette di servire la cartella dell&#8217;<strong>archivio<\/strong> in modo statico, consentendo di scaricare i file di parquet generati dal server.<\/p>\n<p>Non dimenticate di creare una cartella di <strong>archivio<\/strong> nella directory del progetto per memorizzare i file di archivio.<\/p>\n<p>Possiamo personalizzare ulteriormente questo snippet di codice per caricare automaticamente i file di parquet in un <a href=\"https:\/\/sparkbyexamples.com\/spark\/spark-read-write-parquet-file-from-amazon-s3\/\" target=\"_blank\" rel=\"noopener noreferrer\">bucket AWS S3<\/a> e utilizzare i job CRON per attivare automaticamente l&#8217;operazione su una routine.<\/p>\n<h3>5. Pulizia dei dati<\/h3>\n<p>Uno scopo comune dell&#8217;esecuzione di operazioni di manutenzione del database \u00e8 quello di ripulire i dati che diventano vecchi o irrilevanti con il passare del tempo. In questa sezione vengono illustrati due casi comuni in cui la pulizia dei dati viene effettuata come parte della manutenzione.<\/p>\n<p>In realt\u00e0, possiamo impostare una routine di pulizia dei dati come richiesto dai modelli di dati dell&#8217;applicazione. Gli esempi riportati di seguito sono solo di riferimento.<\/p>\n<h4>Eliminare i record per et\u00e0 (ultima modifica o ultimo accesso)<\/h4>\n<p>La pulizia dei record in base all&#8217;et\u00e0 \u00e8 relativamente semplice rispetto alle altre operazioni di questo elenco. Possiamo scrivere una query di cancellazione che elimina i record precedenti a una data stabilita.<\/p>\n<p>Ecco un esempio di cancellazione di commenti fatti prima del 9 ottobre 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>Potete provarlo inviando una richiesta GET alla route <code>\/clean-by-age<\/code>.<\/p>\n<h4>Eliminare i record in base a condizioni personalizzate<\/h4>\n<p>Possiamo anche impostare le pulizie in base ad altre condizioni, come ad esempio la rimozione dei record che non sono collegati ad altri record attivi nel sistema (creando una situazione di <em>orphan<\/em> ).<\/p>\n<p>Ad esempio, possiamo impostare un&#8217;operazione di pulizia che cerchi i commenti collegati ai post cancellati e li elimini perch\u00e9 probabilmente non verranno mai pi\u00f9 visualizzati nell&#8217;applicazione:<\/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>\u00c8 possibile creare delle condizioni specifiche per ciascun caso d&#8217;uso.<\/p>\n<h3>6. Manipolazione dei dati<\/h3>\n<p>Le operazioni di manutenzione del database sono utilizzate anche per effettuare manipolazioni e trasformazioni dei dati, come la censura del linguaggio osceno o la conversione di combinazioni di testo in emoji.<\/p>\n<p>A differenza della maggior parte delle altre operazioni, \u00e8 meglio eseguirle quando si verificano gli aggiornamenti del database (piuttosto che eseguirle su tutte le righe in un periodo fisso della settimana o del mese).<\/p>\n<p>Questa sezione elenca due di queste operazioni, ma l&#8217;implementazione di qualsiasi altra operazione di manipolazione personalizzata rimane abbastanza simile a queste.<\/p>\n<h4>Convertire il testo in Emoji<\/h4>\n<p>Possiamo convertire combinazioni di testo come &#8220;:)&#8221; e &#8220;xD&#8221; in vere e proprie emoji per offrire una migliore esperienza all&#8217;utente e mantenere la coerenza delle informazioni. Ecco uno snippet di codice che ci aiuter\u00e0 a farlo:<\/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>Questo snippet di codice richiede innanzitutto di definire un elenco di emoji e le loro rappresentazioni testuali. Poi, interroga il database per cercare queste combinazioni testuali e le sostituisce con le emoji.<\/p>\n<h4>Censurare il linguaggio osceno<\/h4>\n<p>Un&#8217;operazione piuttosto comune utilizzata nelle app che permettono di creare contenuti generati dagli utenti \u00e8 quella di censurare il linguaggio offensivo. In questo caso l&#8217;approccio \u00e8 simile: identifichiamo le istanze di linguaggio osceno e sostituiamole con dei caratteri asterisco. Possiamo utilizzare il pacchetto bad-words per verificare e censurare facilmente le espressioni volgari.<\/p>\n<p>Installiamo il pacchetto eseguendo il seguente comando:<\/p>\n<pre><code class=\"language-bash\">yarn add bad-words<\/code><\/pre>\n<p>Quindi, inizializziamo il pacchetto nel file <strong>index.js<\/strong>:<\/p>\n<pre><code class=\"language-js\">const Filter = require('bad-words');\nfilter = new Filter();<\/code><\/pre>\n<p>Ora, utilizziamo il seguente frammento di codice per censurare i contenuti osceni nella tabella dei commenti:<\/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>Il codice completo di questo tutorial si trova in <a href=\"https:\/\/github.com\/krharsh17\/node-db-maintenance\" target=\"_blank\" rel=\"noopener noreferrer\">questo repo GitHub<\/a>.<\/p>\n<h2>Cos&#8217;\u00e8 e a cosa serve il processo Vacuum di PostgreSQL<\/h2>\n<p>Oltre a impostare routine di manutenzione personalizzate come quelle discusse sopra, possiamo anche utilizzare una delle funzionalit\u00e0 di manutenzione native che PostgreSQL offre per garantire la salute e le prestazioni del database: <a href=\"https:\/\/www.postgresql.org\/docs\/current\/routine-vacuuming.html\" target=\"_blank\" rel=\"noopener noreferrer\">il processo Vacuum<\/a>.<\/p>\n<p>Il processo Vacuum aiuta a ottimizzare le prestazioni del database e a recuperare spazio su disco. PostgreSQL esegue le operazioni di Vacuum in modo programmato grazie all&#8217;auto-vacuum daemon, ma \u00e8 anche possibile attivarlo manualmente se necessario. Ecco alcuni modi in cui eseguire un processo Vacuum frequentemente pu\u00f2 rivelarsi utile:<\/p>\n<ul>\n<li><strong>Recupero dello spazio su disco bloccato<\/strong>: uno degli obiettivi principali di Vacuum \u00e8 quello di recuperare lo spazio su disco bloccato all&#8217;interno del database. Poich\u00e9 i dati vengono costantemente inseriti, aggiornati e cancellati, PostgreSQL pu\u00f2 essere ingombrato da righe &#8220;morte&#8221; o obsolete che occupano ancora spazio sul disco. Vacuum identifica e rimuove queste righe morte, rendendo lo spazio disponibile per i nuovi dati. Senza Vacuum, lo spazio su disco si esaurirebbe gradualmente, portando potenzialmente a un calo delle prestazioni e persino a un crash del sistema.<\/li>\n<li><strong>Aggiornamento delle metriche del Query Planner<\/strong>: Vacuum aiuta anche PostgreSQL a mantenere aggiornate le statistiche e le metriche utilizzate dal query planner. Il query planner si basa su un&#8217;accurata distribuzione dei dati e su informazioni statistiche per generare piani di esecuzione efficienti. Eseguendo regolarmente Vacuum, PostgreSQL si assicura che queste metriche siano aggiornate, consentendogli di prendere decisioni migliori su come recuperare i dati e ottimizzare le query.<\/li>\n<li><strong>Aggiornamento della mappa di visibilit\u00e0<\/strong>: La mappa di visibilit\u00e0 \u00e8 un altro aspetto cruciale del processo Vacuum di PostgreSQL. Aiuta a identificare quali blocchi di dati in una tabella sono completamente visibili a tutte le transazioni, consentendo a Vacuum di indirizzare solo i blocchi di dati necessari per la pulizia. Questo migliora l&#8217;efficienza del processo Vacuum riducendo al minimo le operazioni di I\/O non necessarie, che sarebbero costose e richiederebbero molto tempo.<\/li>\n<li><strong>Prevenzione dei fallimenti di Transaction ID Wraparound<\/strong>: Vacuum svolge anche un ruolo fondamentale nella prevenzione dei fallimenti dell&#8217;ID transazione. PostgreSQL utilizza un contatore di ID transazione a 32 bit, che pu\u00f2 causare un wraparound quando raggiunge il suo valore massimo. Vacuum contrassegna le vecchie transazioni come &#8220;congelate&#8221;, impedendo al contatore ID di avvolgersi e causare la corruzione dei dati. Trascurare questo aspetto pu\u00f2 portare a guasti catastrofici del database.<\/li>\n<\/ul>\n<p>Come gi\u00e0 detto, PostgreSQL offre due opzioni per l&#8217;esecuzione di Vacuum: <a href=\"https:\/\/www.postgresql.org\/docs\/current\/routine-vacuuming.html#AUTOVACUUM\" target=\"_blank\" rel=\"noopener noreferrer\">Autovacuum<\/a> e <a href=\"https:\/\/www.postgresql.org\/docs\/current\/sql-vacuum.html\" target=\"_blank\" rel=\"noopener noreferrer\">Manual Vacuum<\/a>.<\/p>\n<p>Autovacuum \u00e8 la scelta consigliata per la maggior parte degli scenari, in quanto gestisce automaticamente il processo Vacuum in base alle impostazioni predefinite e all&#8217;attivit\u00e0 del database. Il Vacuum manuale, invece, offre un maggiore controllo ma richiede una conoscenza pi\u00f9 approfondita della manutenzione del database.<\/p>\n<p>La scelta tra le due opzioni dipende da fattori quali le dimensioni del database, il carico di lavoro e le risorse disponibili. I database di piccole e medie dimensioni possono spesso affidarsi all&#8217;Autovacuum, mentre quelli pi\u00f9 grandi o pi\u00f9 complessi possono richiedere un intervento manuale.<\/p>\n<h2>Riepilogo<\/h2>\n<p>La manutenzione dei database non \u00e8 solo una questione di pulizia ordinaria, ma \u00e8 la base di un&#8217;applicazione sana e performante. Ottimizzando, pulendo e organizzando regolarmente i dati, ci si assicura che il database PostgreSQL continui a fornire prestazioni massime, rimanga libero da corruzione e operi in modo efficiente, anche quando l&#8217;applicazione scala.<\/p>\n<p>In questa guida completa abbiamo analizzato l&#8217;importanza fondamentale di stabilire piani di manutenzione del database PostgreSQL ben strutturati quando si lavora con Node.js ed Express.<\/p>\n<p><em>Ci siamo persi qualche operazione di manutenzione ordinaria del database che avete implementato per il vostro database? Oppure conoscete un modo migliore per implementare una delle operazioni sopra descritte? Fatecelo sapere nei commenti!<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Con l&#8217;evoluzione dello sviluppo delle app, i database rappresentano il fulcro della maggior parte delle applicazioni, in quanto immagazzinano e gestiscono dati fondamentali per le aziende &#8230;<\/p>\n","protected":false},"author":238,"featured_media":74711,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kinsta_gated_content":false,"_kinsta_gated_content_redirect":"","footnotes":""},"tags":[],"topic":[26203,26213,25992],"class_list":["post-74710","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","topic-node-js","topic-postgresql","topic-suggerimenti-tecnici"],"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>Impostare piani di manutenzione del database per PostgreSQL su Node.js<\/title>\n<meta name=\"description\" content=\"Scopri la manutenzione del database PostgreSQL su Node.js con la nostra guida completa. Migliora la gestione dei database senza sforzo!\" \/>\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\/it\/blog\/piano-manutenzione-database\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Come impostare dei piani di manutenzione del database per PostgreSQL su Node.js\" \/>\n<meta property=\"og:description\" content=\"Scopri la manutenzione del database PostgreSQL su Node.js con la nostra guida completa. Migliora la gestione dei database senza sforzo!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/\" \/>\n<meta property=\"og:site_name\" content=\"Kinsta\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/kinstaitalia\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-11-23T12:28:39+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-30T12:27:16+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/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=\"Scopri la manutenzione del database PostgreSQL su Node.js con la nostra guida completa. Migliora la gestione dei database senza sforzo!\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/11\/database-maintenance-plan.jpg\" \/>\n<meta name=\"twitter:creator\" content=\"@Kinsta_IT\" \/>\n<meta name=\"twitter:site\" content=\"@Kinsta_IT\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kumar Harsh\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"21 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/\"},\"author\":{\"name\":\"Kumar Harsh\",\"@id\":\"https:\/\/kinsta.com\/it\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9\"},\"headline\":\"Come impostare dei piani di manutenzione del database per PostgreSQL su Node.js\",\"datePublished\":\"2023-11-23T12:28:39+00:00\",\"dateModified\":\"2023-11-30T12:27:16+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/\"},\"wordCount\":3050,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/it\/#organization\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/11\/database-maintenance-plan.jpg\",\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/\",\"url\":\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/\",\"name\":\"Impostare piani di manutenzione del database per PostgreSQL su Node.js\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/it\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/11\/database-maintenance-plan.jpg\",\"datePublished\":\"2023-11-23T12:28:39+00:00\",\"dateModified\":\"2023-11-30T12:27:16+00:00\",\"description\":\"Scopri la manutenzione del database PostgreSQL su Node.js con la nostra guida completa. Migliora la gestione dei database senza sforzo!\",\"breadcrumb\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#primaryimage\",\"url\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/11\/database-maintenance-plan.jpg\",\"contentUrl\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/11\/database-maintenance-plan.jpg\",\"width\":1460,\"height\":730},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kinsta.com\/it\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"PostgreSQL\",\"item\":\"https:\/\/kinsta.com\/it\/argomenti\/postgresql\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Come impostare dei piani di manutenzione del database per PostgreSQL su Node.js\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kinsta.com\/it\/#website\",\"url\":\"https:\/\/kinsta.com\/it\/\",\"name\":\"Kinsta\u00ae\",\"description\":\"Soluzioni di hosting premium, veloci e sicure\",\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/it\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kinsta.com\/it\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kinsta.com\/it\/#organization\",\"name\":\"Kinsta\",\"url\":\"https:\/\/kinsta.com\/it\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/kinsta.com\/it\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/12\/kinsta-logo.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/12\/kinsta-logo.jpeg\",\"width\":500,\"height\":500,\"caption\":\"Kinsta\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/it\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/kinstaitalia\/\",\"https:\/\/x.com\/Kinsta_IT\",\"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\/it\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9\",\"name\":\"Kumar Harsh\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/kinsta.com\/it\/#\/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\/it\/blog\/author\/kumarharsh\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Impostare piani di manutenzione del database per PostgreSQL su Node.js","description":"Scopri la manutenzione del database PostgreSQL su Node.js con la nostra guida completa. Migliora la gestione dei database senza sforzo!","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\/it\/blog\/piano-manutenzione-database\/","og_locale":"it_IT","og_type":"article","og_title":"Come impostare dei piani di manutenzione del database per PostgreSQL su Node.js","og_description":"Scopri la manutenzione del database PostgreSQL su Node.js con la nostra guida completa. Migliora la gestione dei database senza sforzo!","og_url":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/","og_site_name":"Kinsta\u00ae","article_publisher":"https:\/\/www.facebook.com\/kinstaitalia\/","article_published_time":"2023-11-23T12:28:39+00:00","article_modified_time":"2023-11-30T12:27:16+00:00","og_image":[{"width":1460,"height":730,"url":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/11\/database-maintenance-plan.jpg","type":"image\/jpeg"}],"author":"Kumar Harsh","twitter_card":"summary_large_image","twitter_description":"Scopri la manutenzione del database PostgreSQL su Node.js con la nostra guida completa. Migliora la gestione dei database senza sforzo!","twitter_image":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/11\/database-maintenance-plan.jpg","twitter_creator":"@Kinsta_IT","twitter_site":"@Kinsta_IT","twitter_misc":{"Scritto da":"Kumar Harsh","Tempo di lettura stimato":"21 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#article","isPartOf":{"@id":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/"},"author":{"name":"Kumar Harsh","@id":"https:\/\/kinsta.com\/it\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9"},"headline":"Come impostare dei piani di manutenzione del database per PostgreSQL su Node.js","datePublished":"2023-11-23T12:28:39+00:00","dateModified":"2023-11-30T12:27:16+00:00","mainEntityOfPage":{"@id":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/"},"wordCount":3050,"commentCount":0,"publisher":{"@id":"https:\/\/kinsta.com\/it\/#organization"},"image":{"@id":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/11\/database-maintenance-plan.jpg","inLanguage":"it-IT","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/","url":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/","name":"Impostare piani di manutenzione del database per PostgreSQL su Node.js","isPartOf":{"@id":"https:\/\/kinsta.com\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#primaryimage"},"image":{"@id":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/11\/database-maintenance-plan.jpg","datePublished":"2023-11-23T12:28:39+00:00","dateModified":"2023-11-30T12:27:16+00:00","description":"Scopri la manutenzione del database PostgreSQL su Node.js con la nostra guida completa. Migliora la gestione dei database senza sforzo!","breadcrumb":{"@id":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#primaryimage","url":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/11\/database-maintenance-plan.jpg","contentUrl":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/11\/database-maintenance-plan.jpg","width":1460,"height":730},{"@type":"BreadcrumbList","@id":"https:\/\/kinsta.com\/it\/blog\/piano-manutenzione-database\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kinsta.com\/it\/"},{"@type":"ListItem","position":2,"name":"PostgreSQL","item":"https:\/\/kinsta.com\/it\/argomenti\/postgresql\/"},{"@type":"ListItem","position":3,"name":"Come impostare dei piani di manutenzione del database per PostgreSQL su Node.js"}]},{"@type":"WebSite","@id":"https:\/\/kinsta.com\/it\/#website","url":"https:\/\/kinsta.com\/it\/","name":"Kinsta\u00ae","description":"Soluzioni di hosting premium, veloci e sicure","publisher":{"@id":"https:\/\/kinsta.com\/it\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kinsta.com\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Organization","@id":"https:\/\/kinsta.com\/it\/#organization","name":"Kinsta","url":"https:\/\/kinsta.com\/it\/","logo":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/kinsta.com\/it\/#\/schema\/logo\/image\/","url":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/12\/kinsta-logo.jpeg","contentUrl":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/12\/kinsta-logo.jpeg","width":500,"height":500,"caption":"Kinsta"},"image":{"@id":"https:\/\/kinsta.com\/it\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/kinstaitalia\/","https:\/\/x.com\/Kinsta_IT","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\/it\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9","name":"Kumar Harsh","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/kinsta.com\/it\/#\/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\/it\/blog\/author\/kumarharsh\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/posts\/74710","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/users\/238"}],"replies":[{"embeddable":true,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/comments?post=74710"}],"version-history":[{"count":5,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/posts\/74710\/revisions"}],"predecessor-version":[{"id":74849,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/posts\/74710\/revisions\/74849"}],"alternate":[{"embeddable":true,"hreflang":"en","title":"English","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/74710\/translations\/en"},{"embeddable":true,"hreflang":"it","title":"Italian","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/74710\/translations\/it"},{"embeddable":true,"hreflang":"pt","title":"Portuguese","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/74710\/translations\/pt"},{"embeddable":true,"hreflang":"fr","title":"French","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/74710\/translations\/fr"},{"embeddable":true,"hreflang":"de","title":"German","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/74710\/translations\/de"},{"embeddable":true,"hreflang":"ja","title":"Japanese","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/74710\/translations\/jp"},{"embeddable":true,"hreflang":"es","title":"Spanish","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/74710\/translations\/es"},{"href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/74710\/tree"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/media\/74711"}],"wp:attachment":[{"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/media?parent=74710"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/tags?post=74710"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/topic?post=74710"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}