PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Encarts massifs avec promesse pg

MISE À JOUR

Le mieux est de lire l'article suivant :Importations de données .

En tant qu'auteur de pg-promise J'ai été obligé de fournir enfin la bonne réponse à la question, car celle publiée plus tôt ne lui rendait pas vraiment justice.

Afin d'insérer un nombre massif/infini d'enregistrements, votre approche doit être basée sur la méthode séquence , disponible dans les tâches et les transactions.

var cs = new pgp.helpers.ColumnSet(['col_a', 'col_b'], {table: 'tableName'});

// returns a promise with the next array of data objects,
// while there is data, or an empty array when no more data left
function getData(index) {
    if (/*still have data for the index*/) {
        // - resolve with the next array of data
    } else {
        // - resolve with an empty array, if no more data left
        // - reject, if something went wrong
    }        
}

function source(index) {
    var t = this;
    return getData(index)
        .then(data => {
            if (data.length) {
                // while there is still data, insert the next bunch:
                var insert = pgp.helpers.insert(data, cs);
                return t.none(insert);
            }
            // returning nothing/undefined ends the sequence
        });
}

db.tx(t => t.sequence(source))
    .then(data => {
        // success
    })
    .catch(error => {
        // error
    });

C'est la meilleure approche pour insérer un nombre massif de lignes dans la base de données, à la fois du point de vue des performances et de la limitation de la charge.

Il ne vous reste plus qu'à implémenter votre fonction getData selon la logique de votre application, c'est-à-dire d'où proviennent vos données volumineuses, en fonction de l'index de la séquence, pour renvoyer environ 1 000 à 10 000 objets à la fois, selon la taille des objets et la disponibilité des données.

Voir aussi quelques exemples d'API :

Question connexe :node-postgres avec une quantité massive de requêtes .

Et dans les cas où vous avez besoin d'acquérir les identifiants générés de tous les enregistrements insérés, vous devez modifier les deux lignes comme suit :

// return t.none(insert);
return t.map(insert + 'RETURNING id', [], a => +a.id);

et

// db.tx(t => t.sequence(source))
db.tx(t => t.sequence(source, {track: true}))

soyez prudent, car conserver trop d'identifiants d'enregistrement en mémoire peut créer une surcharge.