2016-12-23 5 views
0

Ich versuche 400k Zeilen aus einer mysql Datenbank abzufragen, indem ich 10 auf einmal. Ich brauche eine Rekursion wie dies zu tun, dass asynchron zu verwenden:Wie asynchron eine große Menge von Daten mit Node.js abfragen?

var migrate = function(offset, size) { 
    Mysql.query(query, [offset, size], function(err, rows) { 
    if (!err && rows.length) { 
     setTimeout(function() { 
     // Pretend doing something and get next batch. 
     migrate(offset + size, size); 
     }, 1000); 
    } 
    }); 
}; 

migrate(0, 10); 

Das Problem ist, der erste Aufruf von migrate() ein Kind Rückruf erzeugt von selbst, und alle von ihnen im Gedächtnis bleiben, bis die letzten migrate() fertig ist .

Die einzige Lösung, die in den Sinn kommt, ist es synchron in while Schleife ausführen.

Können Sie bitte beraten, wie man das richtig macht? Vielen Dank.

+0

aa Weg finden, die Menge der Anrufe benötigt werden, um entweder zu reduzieren Schreiben komplexer sql (so brauchen Sie nicht 400k Zeilen) oder nach mehr Zeilen zur gleichen Zeit. Oder holen Sie nur die Zeilen, die Sie sofort verwenden. Wenn Sie am Ende genau 400k Zeilen zur selben Zeit benötigen, gibt es wahrscheinlich ein Designproblem. Sie könnten die Funktion auch so umschreiben, dass sie nicht rekursiv ist, sondern an eine andere Funktion übergeben wird, die die zurückgegebenen Daten verarbeitet und erneut migriert. Wenn Sie die zurückgegebenen Daten klonen oder dereferenzieren, sollten die Prev Ajax-Aufrufe in der Lage sein, Garbage Collected zu sammeln und Speicher freizugeben. – Shilly

Antwort

0

Im aktuellen Beispiel mit mysql Modul kann es durch Abfragen aller Datensätze ohne Chunking und Verwendung mit Streaming query rows erfolgen. Es wird Abfragen nacheinander ausführen, sobald das Ergebnis verarbeitet wurde.

Mysql.query(sql).on('result', function(row) { 
    Mysql.pause(); 
    setTimeout(function() { 
    // Pretend doing something. 
    Mysql.resume(); 
    }, 1000); 
}); 

Aber (!), Sollte result Rückruf keine Verschlussgrößen haben, weil in diesem Fall diese Variablen die Erinnerung bleiben werden. Ich habe ein paar Benchmarks gemacht, so weiß ich es, kann es nicht anders erklären.

Im Allgemeinen, wenn Sie eine große Menge an Daten verarbeiten müssen, spielt keine Rolle, es ist ein mysql oder etwas anderes, würde ich empfehlen:

  1. Verwendung streams.
  2. Verwenden Sie process.nextTick().
  3. Verwenden Sie keine Verschlüsse.
  4. Verwenden Sie keine Rekursionen.
+0

Guter Rat. Technisch gesehen könnten Sie Closures und Rekursionen verwenden, wenn Sie Streams richtig verwendet haben. Sie werden nur dann problematisch, wenn sie große Speichermengen speichern, was bei Streams nicht möglich ist –

0

einen Blick auf SynJS Take - es ermöglicht synchron Javascript-Code ausgeführt wird:

var SynJS = require('synjs'); 
var mysql  = require('mysql'); 
var connection = mysql.createConnection({ 
    host  : 'localhost', 
    user  : 'tracker', 
    password : 'tracker123', 
    database : 'tracker' 
}); 


function myMigrate(modules,connection) { 
    for(var i=0; i<4; i++) { 
     connection.query("SELECT CONCAT('processing data batch #',?) as res",[i], function(err, rows, fields) { 
       if (err) throw err; 
       console.log(i,rows[0].res); 
       modules.SynJS.resume(_synjsContext); 
     }); 
     SynJS.wait(); 
    } 
}; 

var modules = { 
     SynJS: SynJS, 
     mysql: mysql, 
}; 

SynJS.run(myMigrate,null,modules,connection,function() { 
    console.log('done'); 
}); 

Ergebnis wäre:

0 'processing data batch #0' 
1 'processing data batch #1' 
2 'processing data batch #2' 
3 'processing data batch #3' 
done 
Verwandte Themen