2017-01-24 4 views
0

Je suis aux prises avec une question - comment puis-je insérer ou mettre à jour un grand nombre de données (des milliers ou des millions de lignes) en utilisant le pilote node oracle-db? Le point est que je peux sélectionner beaucoup de données à l'aide de resultSet (handling result set) ... mais alors je dois faire quelques actions avec une ligne et mettre à jour plus tard ou insérer une nouvelle ligne. Et voici le problème - je ne sais pas comment le faire aussi vite que possible.Comment mettre à jour ou insérer des millions de lignes via le nœud oracle-db?

Quelqu'un peut-il m'aider avec un conseil? Merci.

+0

Quelles sont les "actions avec une rangée" qui doivent être effectuées? En général, si vous pouvez le faire dans la base de données, plutôt que de récupérer des millions de lignes sur un client ou un serveur d'application, vous serez bien mieux ... – BobC

+0

Je peux vous assurer que ces actions ne peuvent pas être effectuées en db . Par exemple, il y a une sorte de logique qui prend un rang à partir de db, fait des calculs et me donne ensuite un nombre. Et ce numéro je voudrais insérer (ou mettre à jour) dans une autre table. – alingo

+0

Prendre un rang, faire des calculs et obtenir un nombre sonne exactement le genre de chose qu'une base de données est très bonne! – BobC

Répondre

0

Je peux vous assurer que ces actions ne peuvent pas être effectuées en db.

En fait, il existe de nombreuses façons de procéder dans la base de données via SQL et PL/SQL si nécessaire. Les gens veulent souvent utiliser le langage avec lequel ils sont à l'aise, peut-être JavaScript dans ce cas, mais les performances seront bien meilleures si les données ne doivent pas circuler entre les niveaux.

Voici un exemple en SQL uniquement ... Certes, cela aurait pu être fait via des colonnes virtuelles, mais cela devrait illustrer le point.

Imaginez que nous avons les tableaux suivants:

create table things (
    id number not null, 
    val1 number not null, 
    val2 number not null, 
    constraint things_pk primary key (id) 
); 

insert into things (id, val1, val2) values (1, 1, 2); 
insert into things (id, val1, val2) values (2, 2, 2); 
insert into things (id, val1, val2) values (3, 5, 5); 

-- Will hold the sum of things val1 and val2 
create table thing_sums (
    thing_id number, 
    sum  number 
); 

alter table thing_sums 
add constraint thing_sums_fk1 
foreign key (thing_id) 
references things (id); 

Maintenant, la façon de le faire le plus simple et plus performant que ce serait via SQL:

insert into thing_sums (
    thing_id, 
    sum 
) 
select id, 
    val1 + val2 
from things 
where id not in (
    select thing_id 
    from thing_sums 
); 

Voici un autre exemple qui fait la même chose que via PL/SQL qui peut fournir plus de contrôle.

begin 

    -- This cursor for loop will bulk collect (reduces context switching between 
    -- SQL and PL/SQL engines) implictly. 
    for thing_rec in (
    select * 
    from things 
    where id not in(
     select thing_id 
     from thing_sums 
    ) 
) 
    loop 
    -- Logic in this loop could be endlessly complex. I'm inserting the values 
    -- within the loop but this logic could be modified to store data in arrays 
    -- and then insert with forall (another bulk operation) after the loop. 
    insert into thing_sums(
     thing_id, 
     sum 
    ) values (
     thing_rec.id, 
     thing_rec.val1 + thing_rec.val2 
    ); 
    end loop; 

end; 

L'un ou l'autre de ces éléments peut être appelé à partir du pilote Node.js. Cependant, disons que vous devez le faire depuis le pilote (peut-être que vous êtes en train d'intégrer des données qui ne sont pas déjà dans la base de données). Voici un exemple montrant l'appel PL/SQL à partir du pilote qui utilise le traitement en bloc plutôt que des opérations ligne par ligne. C'est beaucoup plus rapide en raison des allers-retours réduits.

J'ai tiré ce d'un billet de blog je travaille donc la définition de la table est un peu différent:

create table things (
    id number not null, 
    name varchar2(50), 
    constraint things_pk primary key (id) 
); 

Et voici le JavaScript:

var oracledb = require('oracledb'); 
var async = require('async'); 
var config = require('./dbconfig'); 
var things = []; 
var idx; 

function getThings(count) { 
    var things = []; 

    for (idx = 0; idx < count; idx += 1) { 
    things[idx] = { 
     id: idx, 
     name: "Thing number " + idx 
    }; 
    } 

    return things; 
} 

things = getThings(500); 

oracledb.getConnection(config, function(err, conn) { 
    var ids = []; 
    var names = []; 
    var start = Date.now(); 

    if (err) {throw err;} 

    // We need to break up the array of JavaScript objects into arrays that 
    // work with node-oracledb bindings. 
    for (idx = 0; idx < things.length; idx += 1) { 
    ids.push(things[idx].id); 
    names.push(things[idx].name); 
    } 

    conn.execute(
    ` declare 
     type number_aat is table of number 
      index by pls_integer; 
     type varchar2_aat is table of varchar2(50) 
      index by pls_integer; 

     l_ids number_aat := :ids; 
     l_names varchar2_aat := :names; 
     begin 
     forall x in l_ids.first .. l_ids.last 
      insert into things (id, name) values (l_ids(x), l_names(x)); 
     end;`, 
    { 
     ids: { 
     type: oracledb.NUMBER, 
     dir: oracledb.BIND_IN, 
     val: ids 
     }, 
     names: { 
     type: oracledb.STRING, 
     dir: oracledb.BIND_IN, 
     val: names 
     } 
    }, 
    { 
     autoCommit: true 
    }, 
    function(err) { 
     if (err) {console.log(err); return;} 

     console.log('Success. Inserted ' + things.length + ' rows in ' + (Date.now() - start) + ' ms.'); 
    } 
); 
}); 

J'espère que ça aide! :)

+0

C'est génial! Je pense que c'est ce que je cherchais. Merci beaucoup!!! Btw, votre article de blog est en cours ou je peux le trouver sur internet? – alingo

+0

Ce poste particulier n'est pas encore sorti, mais vous pouvez visiter le blog ici: https://jsao.io/ –

+0

@ Le poste de DanMcGhan est à https://jsao.io/2017/01/plsql-record-types- et-le-noeud-js-pilote / –