2016-07-12 43 views
1

我正在寫一個ETL工具,它與一個Oracle數據庫進行交互,該數據庫也使用node-oracledb1.10RxJS來處理我所徘徊的所有各種異步數據流。我遇到了一個問題,我的應用運行時間越長,node-oracledb.execute()需要的呼叫時間就越長,並且它在運行時間內線性增加。希望你可以在下面的代碼中發現錯誤並糾正它。爲什麼我的node-oracledb執行Promise穩步增加需要解決的時間?

首先讓我演示如何運行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()函數的一個例子。正如你所看到的,這裏有很多事情發生,所以爲了清晰起見,讓我試着對它進行註釋。 rnd用於爲console.time()創建唯一的ID,因此我可以跟蹤解決.execute()Promise需要的時間。讓我知道這次測量技術是否存在缺陷。傳遞給SELECT語句的綁定輸入變量是ssid標識符的csv字符串,並且將返回匹配列表。這允許我批處理記錄,而不是爲每個單獨的行創建單個查詢,希望節省一些執行時間。第一個.then()使所得到的對象數組中的每個鍵都爲小寫。第二個.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; 
    }); 

下面是console.time()輸出,這增加了穩步,直至碰到60000毫秒queueTimeout限制。

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 

我試圖包含大部分相關的代碼,請讓我知道如果您需要更多的上下文。

編輯:

我加了一個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

相關問題