Ich schreibe ein ETL-Tool, das mit einer Oracle
-Datenbank interagiert, die auch node-oracledb
1.10
und RxJS
verwendet, um alle verschiedenen asynchronen Datenströme zu behandeln, die ich herumwerfen. Ich stoße auf ein Problem, wo je länger meine Anwendung läuft, desto länger dauert ein Anruf an node-oracledb
's .execute()
, und es scheint in der Laufzeit linear zu erhöhen. Hoffentlich können Sie den Fehler im folgenden Code erkennen und korrigieren.Warum führt mein node-oracledb Promise immer schneller in der Zeit aus, die zur Lösung benötigt wird?
Lassen Sie mich zuerst zeigen, wie ich Oracle-Abfragen ausführen. Ich habe meine eigene Funktion erstellt, die als Wrapper um node-oracledb
's .execute()
fungiert.
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;
}
Und mein config.database.oracle
(ohne die Anmeldeinformationen):
{
"poolTimeout": 60,
"poolMin": 10,
"poolMax": 25,
"queueRequests": true,
"queueTimeout": 600000,
"_enableStats": true
}
Im Folgenden ist ein Beispiel für mich meine .execute()
Funktion aufgerufen wird. Wie du sehen kannst, passiert hier sehr viel, also lass mich versuchen, es ein wenig zu kommentieren, um es zu verdeutlichen. rnd
wird verwendet, um eine eindeutige ID für console.time()
zu erstellen, damit ich die Zeit aufzeichnen kann, die für die Zeit benötigt. Lassen Sie mich wissen, ob es einen Fehler in dieser Zeitmessungstechnik gibt. Die bind-Eingabevariable, die an die SELECT
-Anweisung übergeben wird, ist eine CSV-Zeichenfolge mit ssid-Bezeichnern, und eine Liste mit Übereinstimmungen wird zurückgegeben. Dadurch kann ich Datensätze im Stapel verarbeiten, anstatt für jede einzelne Zeile eine einzige Abfrage zu erstellen. Die erste macht jeden Schlüssel in dem resultierenden Array von Objekten in Kleinbuchstaben. Die zweite beendet natürlich die console.time()
Verfolgung.
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;
});
Unten ist die console.time()
Ausgabe, die stetig zunimmt, bis er die 60000 ms queueTimeout
Grenze trifft.
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
Ich habe versucht, den größten Teil des entsprechenden Codes enthalten, lassen Sie mich bitte wissen, wenn Sie mehr Kontext benötigen.
EDIT:
Ich habe eine console.log(pool._logStats())
Anweisung jedes Mal die .execute()
Funktion aufgerufen wird. Ich habe den Ausgang der letzten Zeit enthalten sie vor dem NJS-040
Fehler gedruckt wurde:
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