2015-03-24 10 views
6

Sto tentando di esportare un'intera tabella di database sqlite3 in CSV utilizzando knex.js. Poiché la tabella può contenere fino a 300000 righe, io uso gli stream per non avere problemi di memoria. Ma se guardo l'utilizzo della memoria della mia app fino a 800 MB o ho un errore di "memoria insufficiente".Problemi di memoria su knex.js durante l'utilizzo di stream

Come posso gestire un risultato di query di grandi dimensioni con knex.js nel database sqlite3?

Qui di seguito un esempio di codice:

knex.select().from(table).stream(function (stream) { 
    var stringifier = stringify(opts); 
    var fileStream = fs.createWriteStream(file); 

    var i = 0; 
    stringifier.on('readable', function() { 
     var row; 
     while (row = stringifier.read()) { 
     fileStream.write(row); 
     console.log("row " + i++); //debug 
     } 
    }); 

    fileStream.once('open', function(fd) { 
     stream.pipe(stringifier); 
    }); 
}); 

EDIT

Sembra flussi knex.js per sqlite3 banca dati sono flussi di "falsi". Sotto il codice sorgente della funzione di corrente per sqlite3 in knex:

Runner_SQLite3.prototype._stream = Promise.method(function(sql, stream, options) { 
    /*jshint unused: false*/ 
    var runner = this; 
    return new Promise(function(resolver, rejecter) { 
     stream.on('error', rejecter); 
     stream.on('end', resolver); 
     return runner.query(sql).map(function(row) { 
      stream.write(row); 
     }).catch(function(err) { 
      stream.emit('error', err); 
     }).then(function() { 
      stream.end(); 
     }); 
    }); 
}); 

Vediamo che attende la richiesta sia eseguita prima creare il flusso dalla matrice risultato.

VERSIONE:

  • Knex.Js 0.7.5
  • nodo 0,12

Thx per il vostro aiuto.

risposta

3

Penso che non ci siano soluzioni. Uso limite e offset per ottenere tutti i dati passo dopo passo con knex.js e scrivo ogni riga in un flusso di scrittura. Un esempio di implementazione per coloro che desiderano:

exportTable: function(table, writeStream) { 
    var totalRows; 
    var rowLimit = _config.ROW_LIMIT; 

    return DatabaseManager.countAll(table).then(function(count) { 

     totalRows = count[0]['count(*)']; 
     var iterations = new Array(Math.ceil(totalRows/rowLimit)); 

     return Promise.reduce(iterations, function(total, item, index) { 

      return _knex.select().from(table).limit(rowLimit).offset(index * rowLimit).map(function(row) { 
       writeStream.write(row); 
      }).catch(function(err) { 
       return Promise.reject(err); 
      }); 

     }, 0).then(function() { 
      return Promise.resolve(); 
     }).catch(function(err) { 
      return Promise.reject(err); 
     }); 

    }).catch(function(err) { 
     console.log(err); 
     return Promise.reject(err); 
    }); 
}