2017-01-24 15 views
0

노드 oracle-db 드라이버를 사용하여 많은 데이터 (수천 또는 수백만 행)를 삽입하거나 업데이트하려면 어떻게해야합니까?노드 oracle-db를 통해 수백만 개의 행을 업데이트하거나 삽입하는 방법은 무엇입니까?

요점은 resultSet (handling result set)의 도움으로 많은 데이터를 선택할 수 있다는 것입니다.하지만 행과 함께 몇 가지 작업을하고 나중에 새 행을 업데이트하거나 삽입해야합니다. 그리고 여기에 문제가 있습니다 - 나는 그것을 가능한 한 빨리하는 법을 모른다.

아무도 도와 줄 수 있습니까? 감사.

+0

수행해야하는 "행이있는 작업"은 무엇입니까? 일반적으로 클라이언트 또는 응용 프로그램 서버로 수백만 행을 다시 검색하는 대신 데이터베이스에서이를 수행 할 수 있다면 훨씬 더 나아질 것입니다. – BobC

+0

이러한 작업을 db . 예를 들어, DB에서 행을 취하고 계산을 한 다음 나에게 숫자를 제공하는 일종의 논리가 있습니다. 그리고이 번호는 다른 테이블에 삽입 (또는 업데이트)하고 싶습니다. – alingo

+0

행을 가져 와서 몇 가지 계산을 수행하고 숫자를 얻는 것은 데이터베이스가 매우 훌륭하게 처리되는 것과 같습니다. – BobC

답변

0

나는 이러한 작업을 db로 수행 할 수 없다는 것을 확신 할 수 있습니다.

사실, 필요한 경우 SQL 및 PL/SQL을 통해 DB에서 수행 할 수있는 많은 다른 방법이 있습니다. 사람들은 자신이 편한 언어 (이 경우 JavaScript)를 사용하기를 원하지만 데이터가 계층간에 이동하지 않아도 성능이 훨씬 좋아집니다.

다음은 SQL 혼자의 예입니다. 가상 컬럼을 통해이 작업을 수행 할 수는 있지만 그 요점을 설명해야합니다.

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); 

지금,이 작업을 수행하는 가장 쉽고 성능이 좋은 방법은 SQL을 통해 다음과 같습니다 : 여기

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

같은 일 만하지 다른 예입니다

우리는 다음과 같은 테이블이 상상 PL/SQL을 통해 더 많은 제어를 제공 할 수 있습니다.

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; 

이 중 하나는 Node.js 드라이버에서 호출 할 수 있습니다. 그러나 드라이버에서이 작업을 수행해야한다고 가정 해 봅시다 (이미 데이터베이스에없는 데이터를 처리하고있을 수도 있습니다). 다음은 행 처리 방식이 아닌 대량 처리 방식을 사용하는 드라이버에서 PL/SQL을 호출하는 예제입니다. 왕복 감소로 인해 훨씬 ​​빨라졌습니다.

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

그리고 여기 자바 스크립트는 다음과 같습니다 :

내가 일하고 있어요 블로그 게시물에서이 뽑아

때문에 테이블 정의는 조금 다르다

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.'); 
    } 
); 
}); 

나는 희망이 도움이! :)

+0

좋습니다! 나는 이것이 내가 찾고있는 것이라고 생각한다. 정말 고마워!!! Btw, 진행중인 블로그 게시물입니까, 아니면 인터넷에서 찾을 수 있습니까? – alingo

+0

해당 게시물은 아직 공개되지 않았지만 https://jsao.io/ –

+0

@ DanMcGhan의 게시물은 https://jsao.io/2017/01/plsql-record-types- and-the-node-js- 드라이버 / –