ノードのストリーム数百万の行を取得します.js


これまでにデータベースからの列の多くのデータの数百万行を取得し、Web上で表示の課題に直面する必要がありますか?
さて、私は最近これをしなければなりませんでした.これが全く意味をなさないと確信していなかったけれども、私はまだそれをしなければなりませんでした.
とにかく、ここで解決策です.
しかし、最初に、技術スタック:ノード.JSは、シーケンス&マリアブ.クライアントは重要ではありませんでした、なぜならば、時々データはほぼ4 GBの大きかったので、結局、クロムは結局クラッシュしました.
順序付けは最初の大きな問題でした.
このような大きなデータの結果を得るための解決策はストリーミングです.つの大きな呼び出しでそのデータを受け取ると、ノードがクラッシュしました.それで、ストリーミングは答えです、そして、sequelizeはその時点でストリーミングを支持しませんでした.
さて、私は手動でシーケンサにストリーミングを加えることができました、しかし、サービス呼び出しは最終的に年齢をとります.
ここでは、通常のシーケンスの呼び出しの一部を示します.
await sequelize.authenticate();
const result = await sequelize.query(sql, { type: sequelize.QueryTypes.SELECT });
res.send(result);
それです.もちろん、一部は欠落している.全体のデータベース構成と実際の定義のようにget() 呼び出し(例:res か?)しかし、私は、あなたが考えを得ると思います.
このコードを実行すると、結果は簡単です.ノードクラッシュ.ノードをメモリに与えることができます--max-old-space-size=8000 , 例えば、それは本当の解決策ではありません.
既に述べたように、データをストリームするには、強制的に並べ替えができます.今、どのように見えるでしょうか?
var Readable = stream.Readable;
var i = 1;
var s = new Readable({
    async read(size) {
        const result = await sequelize.query(
            sql + ` LIMIT 1000000 OFFSET ${(i - 1) * 1000000}`, { type: sequelize.QueryTypes.SELECT });
        this.push(JSON.stringify(result));
        i++;
        if (i === 5) {
            this.push(null);
        }
    }
});
s.pipe(res);
この例では、データベースから戻ってくる行の数を知っていましたif (i === 5) . それはちょうどテストでした.あなたが送信する必要がありますnull ストリームを終了するにはもちろん、得ることができるcount 結果全体を最初に変更し、それに応じてコードを変更します.
この背後にある考え方は、より小さなデータベースコールを作成し、ストリームの助けを借りてチャンクを返すことです.これは、ノードがクラッシュしないが動作しますが、それはまだ3.5 GBの-ほぼ10分をとります.

代替品は?
The MariaDB Node.js connector .
これは通常のクエリのようになります.
const mariadb = require('mariadb');
const pool = mariadb.createPool({ host: "HOST", user: "USER", password: "PASSWORD", port: 3308, database: "DATABASE", connectionLimit: 5 });
let conn = await pool.getConnection();
const result = await conn.query(sql);
res.send(result);
それははるかに高速です.しかし、ストリーミングコードを右にジャンプさせてください.
let conn = await pool.getConnection();
const queryStream = conn.queryStream(sql);
const ps = new stream.PassThrough();
const transformStream = new stream.Transform({
    objectMode: true,
    transform: function transformer(chunk, encoding, callback) {
        callback(null, JSON.stringify(chunk));
    }
});
stream.pipeline(
    queryStream,
    transformStream,
    ps,
    (err) => {
        if (err) {
            console.log(err)
            return res.sendStatus(400);
        }
    })
ps.pipe(res);
これは少し潜在的に見えるかもしれませんが、ここで起こることは、あなたがものを通過するパイプラインを作成することです.第一にqueryStream データベースクエリの結果です.でtransformStream 文字列とバッファのみを文字列化したものを送信するには、オブジェクトを文字列で返します.そして最後にPassThrough とエラーの場合の関数です.
With ps.pipe(res) 結果をクライアントにストリームします.
結果は以下の通りです.

同じデータのために4分未満で、あなたはそのノードがビットRAMを必要とするのを気づかないでしょう.
だから、同じようなタスクに挑戦している場合は、データのストリーミングについて考えてください.
または、この種の要件がウェブにとって非現実的であることをクライアントに納得させる.
P . S .ページネーションはオプションではありませんでした.我々はすぐに全データを必要とした.
によるイメージfreepik.com .

しかし、待って、もっと!
  • 接続しましょう.
  • ゲット5 Software Developer’s Career Hacks 無料で.
  • あなたの開発者の生活とキャリアのためのより貴重な記事をお楽しみくださいpatrickgod.com .