分配失败 - 处理来自大型SQL查询结果的内存不足错误

时间:2016-01-19 19:11:16

标签: javascript sql node.js tedious

我使用TediousRxJS对SQL Server运行SQL查询,并使用Observable发出结果。此函数定义此行为:

export function msExecute(sql) {
  return new Observable(observer => {
    config.database.sams.requestTimeout = 60000;

    var connection = new mssql.Connection(config.database.sams, function (err) {
      var request = new mssql.Request(connection);
      request.stream = true;
      request.query(sql);
      request.on('row', row => {
        observer.next(row);
      });
      request.on('error', err => {
        observer.error(err);
      });
      request.on('done', () => {
        observer.complete();
        connection.close();
      });
    });
    connection.on('error', error => console.log(`mssql error == ${error}`));
  });
}

我有一个SQL查询,返回我要处理的~110k记录,但是在执行过程中出现了这个错误:

<--- Last few GCs --->

   27330 ms: Scavenge 1396.7 (1457.4) -> 1396.7 (1457.4) MB, 1.4 / 0 ms (+ 2.0 ms in 1 steps since last GC) [allocation failure] [incremental marking delaying mark-sweep].
   28635 ms: Mark-sweep 1396.7 (1457.4) -> 1396.6 (1457.4) MB, 1304.9 / 0 ms (+ 2.9 ms in 2 steps since start of marking, biggest step 2.0 ms) [last resort gc].
   29936 ms: Mark-sweep 1396.6 (1457.4) -> 1396.5 (1457.4) MB, 1300.3 / 0 ms [last resort gc].


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x4035aee3ac1 <JS Object>
    1: /* anonymous */(aka /* anonymous */) [/home/njones/projects/test-forge/node_modules/orawrap/lib/connectionmanager.js:250] [pc=0x20cbecafa065] (this=0x4035ae04189 <undefined>,resolve=0x3896ea762871 <JS Function resolvePromise (SharedFunctionInfo 0x203f09a91f11)>,reject=0x3896ea762829 <JS Function rejectPromise (SharedFunctionInfo 0x203f09a91fb9)>)
    2: lib$es6$promise$$internal$$initiali...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory

我不需要我曾经拥有的所有结果,因此将结果分组到单独的查询中的解决方案可行,我只是不确定如何执行此操作。

1 个答案:

答案 0 :(得分:0)

在这种情况下,您应该使用Node.js流。很难提供更具体的建议,因为不清楚你对SQL查询结果做了什么。

基本上你应该pipe query results到你自己的流:

request.pipe(stream);

使用流,您的查询结果输出将不时暂停,以便以小块的形式处理结果,而不会因系统资源耗尽一个巨大的结果。

或者,您可以尝试直接从流中阅读:

request.read();

通常,流只对字符串和缓冲区进行操作。 object mode中的流可以发出除缓冲区和字符串之外的通用JavaScript值。假设您的request是对象模式的流,read()应返回结果的一行。

Streams是非常重要但又有些棘手的Node.js部分。查看Stream Handbook了解详情。