[컴][js] AdoniJS 에서 큰 DB data 를 retrieve 할 때

chunk / big data / adonijs lucid big data / database cursor / adonis 에서 cursor 사용방법 / db query / size / big size / 쿼리 / node query / how to handle big query result


AdonisJS Lucid 에서 stream 사용

AdonisJS-lucid 의 사용에서 큰 결과 값을 갖는 query 를 다룰 때 stream 을 사용하면 된다. 일반적인 cursor 의 사용이라고 생각하면 될 듯 하다.

AdonisJS Lucid 의 문서에서는 찾기가 힘들었는데, community 에서 자료를 찾았다.(ref. 1)

내용을 정리하면, Lucid는 KnexJS 를 사용하고 있고, KnexJS 에서 streams 를 제공한다. 그것의 사용법은 아래와 같다.

아래 stream 의 예제는 ref. 1 을 참고해서 만들었다.

const ccursor =
  Database.connection('cocktail')
    .raw(
      `SELECT * FROM point AS t1 WHERE t1.id !='tester'
      ORDER BY id ASC`
    ).stream()
  
const prom = new Promise((resolve, reject)=>{
    Logger.error('test2');
    ccursor.on('data', (row)=>{
      Logger.info('test-data');
    })
    ccursor.on('end', () => {
      Logger.info('test-data');
      resolve()
    })
    ccursor.on('error', (param1) => {
      Logger.error('test-error : ' + param1);
      reject()
    })
});
await prom.then((val)=>{
    Logger.info('test-resolve');
}).catch((val)=>{
    Logger.error('test-reject');
});


위의 code 를 실행하면 Logger.info('test-data'); 가 계속 실행되다가 끝날때 Logger.info('test-data'); 가 실행될 것이다.

또는 아래처럼 작성해도 된다.
const prom = new Promise((resolve, reject)=>{
  const ccursor =
    Database.connection('cocktail')
      .raw(
        `SELECT * FROM g5_point AS t1 WHERE t1.mb_id !='admin'
        ORDER BY po_id ASC`
      ).stream();
  ccursor.on('data', (row)=>{
    Logger.error('test-data');
  })
  ccursor.on('end', () => {
    Logger.error('test-end');
    resolve()
  })
  ccursor.on('error', (param1) => {
    Logger.error('test-error : ' + param1);
    reject()
  })
});
await prom.then((val)=>{
  Logger.error('test-resolve');
}).catch((val)=>{
  Logger.error('test-reject');
});


async

아래처럼 async 를 사용할 수 있다.

const prom = new Promise(async (resolve, reject)=>{
  const ccursor =
    Database.connection('cocktail')
      .raw(
        `SELECT * FROM g5_point AS t1 WHERE t1.mb_id !='admin'
        ORDER BY po_id ASC`
      ).stream();
  ccursor.on('data', async (row)=>{
    Logger.error('test-data');
  })
  ccursor.on('end', async () => {
    Logger.error('test-end');
    resolve()
  })
  ccursor.on('error', async (param1) => {
    Logger.error('test-error : ' + param1);
    reject()
  })
});
await prom.then((val)=>{
  Logger.error('test-resolve');
}).catch((val)=>{
  Logger.error('test-reject');
});



아직은 사용하기가 쉽지 않다. 그리고 await/async 와 잘 맞지 않아 보인다. 그래서 자꾸 memory 가 넘치는 듯 하다.

개인적으로 현재로서는 그냥 offset, limit 을 이용해서 일정부분만 retrieve 해서 가져와서 사용하고, 다시 또 일정부분을 가져와서 사용하는 방식이 더 나아 보인다.



See Also

  1. laravel 에서 큰 Database result 를 처리할 때

References

  1. A Way to process large results of database Query in Adonis without consuming too much RAM - Help / Database - Forum - AdonisJS Framework
  2. Knex.js - A SQL Query Builder for Javascript


댓글 없음:

댓글 쓰기