2016-07-12 10 views
1

Oracleデータベースとやり取りするETLツールを作成しています。このツールは、私が投げかけているさまざまな非同期データストリームをすべて処理するのに、node-oracledb1.10RxJSも使用しています。私はアプリケーションが長く実行されるほど、node-oracledb.execute()への呼び出しが長くなり、実行時間が直線的に増加するように見える問題にぶつかっています。うまくいけば、以下のコードで間違いを見つけて修正することができます。私のnode-oracledbはなぜ実行されるのですか?

まず、Oracleの問合せの実行方法を示します。私は自分の.execute()関数を作成し、node-oracledb.execute()のラッパーとして機能します。

import oracledb from 'oracledb'; 
var oraConnPool; 

export function execute(sql, bind, opts) { 
    if (!oraConnPool) { 
    createOraPool(); 
    } 
    return oraConnPool 
    .then(pool => pool.getConnection()) 
    .then(conn => conn.execute(sql, bind, opts)); 
} 

function createOraPool() { 
    let oraPool = oracledb.createPool(config.database.oracle); 
    oraConnPool = oraPool; 
    return oraPool; 
} 

そして、(資格情報なし)私のconfig.database.oracle

{ 
    "poolTimeout": 60, 
    "poolMin": 10, 
    "poolMax": 25, 
    "queueRequests": true, 
    "queueTimeout": 600000, 
    "_enableStats": true 
} 

以下は私の.execute()機能を呼び出すの一例です。ご覧のとおり、ここでは多くのことが起こっているので、わかりやすくするために少し注釈をつけてみましょう。 rndconsole.time()の一意のIDを作成するために使用されるので、.execute()Promiseが解決するのにかかる時間を記録できます。この時間測定技術に欠陥があるかどうかを教えてください。 SELECTステートメントに渡されるバインド入力変数は、ssid識別子のcsv文字列であり、一致のリストが返されます。これにより、個々の行ごとに1つのクエリを作成するのではなく、レコードをバッチ処理して、実行時間を節約できます。最初の.then()は、オブジェクトの結果の配列内のすべてのキーを小文字にします。第2の.then()は、明らかに、console.time()の追跡を終了する。以下

const rnd = Math.random() * 100; 
console.time(rnd); 
return execute(` 
    SELECT 
    ssid_input.ssid AS ssid, 
    students.id AS student_id, 
    students.student_number AS student_number 
    FROM (
     SELECT REGEXP_SUBSTR(
        :ssids, 
        '[^,]+', 1, level) AS ssid 
     FROM dual 
     CONNECT BY REGEXP_SUBSTR(
         :ssids, 
         '[^,]+', 1, level) IS NOT NULL 
) ssid_input 
    LEFT JOIN students ON students.state_studentnumber = ssid_input.ssid`, { 
    ssids: { 
     val: ssids.join(','), 
     dir: orawrap.BIND_IN, 
     type: orawrap.STRING 
    } 
    }, { 
    outFormat: orawrap.OBJECT, 
    maxRows: ssids.length 
    }) 
    .then(results => { 
    return results.rows.map(result => { 
     let newObj = {}; 
     Object.keys(result).forEach(key => { 
     newObj[key.toLowerCase()] = result[key]; 
     }); 
     return newObj; 
    }); 
    }) 
    .then(result => { 
    console.timeEnd(rnd); 
    return result; 
    }); 

が60000ミリqueueTimeout限界に達するまで着実に増加console.time()出力されます。

97.24179652744425: 12226.930ms 
38.14057213652584: 14583.518ms 
46.19793585774834: 16024.785ms 
16.12600313565251: 17820.694ms 
87.73720584788988: 20809.461ms 
54.711100085462604: 22652.638ms 
42.474404414891744: 24037.868ms 
49.09845121453702: 26521.596ms 
87.70258724764568: 29461.480ms 
1.0731996619882223: 31210.875ms 
90.33430329792829: 32259.944ms 
37.4829457960367: 34076.824ms 
9.731832830291932: 35292.281ms 
/home/nathanjones/Projects/test-forge/node_modules/@reactivex/rxjs/dist/cjs/util/subscribeToResult.js:41 
      root_1.root.setTimeout(function() { throw err; }); 
               ^

Error: NJS-040: connection request timeout 

関連するコードの大部分を含めるようにしました。詳細が必要な場合は教えてください。

EDIT:

私はconsole.log(pool._logStats())声明に.execute()関数が呼び出されるたびに追加しました。私はそれがNJS-040エラーの前に印刷された前回の出力を含めました:

Pool statistics: 
...total up time (milliseconds): 62823 
...total connection requests: 1794 
...total requests enqueued: 1769 
...total requests dequeued: 0 
...total requests failed: 0 
...total request timeouts: 0 
...max queue length: 1769 
...sum of time in queue (milliseconds): 0 
...min time in queue (milliseconds): 0 
...max time in queue (milliseconds): 0 
...avg time in queue (milliseconds): 0 
...pool connections in use: 25 
...pool connections open: 25 
Related pool attributes: 
...queueRequests: true 
...queueTimeout (milliseconds): 60000 
...poolMin: 10 
...poolMax: 25 
...poolIncrement: 1 
...poolTimeout (seconds): 60 
...stmtCacheSize: 30 
Related environment variables: 
...process.env.UV_THREADPOOL_SIZE: undefined 
undefined 

答えて

3

これはIssue 474におけるノードORACLEDBレポで議論と分析されています。

接続を閉じる必要があります。

おそらく増加する必要があります。UV_THREADPOOL_SIZE

関連する問題