为什么在使用 Node.js 将数千行插入 Oracle 表时会发生这种情况?

如何解决为什么在使用 Node.js 将数千行插入 Oracle 表时会发生这种情况?

我是 Oracle 的新手,我正在寻找将数千(可能数百万)条记录插入到表中的最佳方法。

我已经看到有关这种情况的其他问题和答案,但在此 answer 中,PL/SQL 代码使用了两个标量类型 (PSL_INTEGER) 关联数组,并用作表列,我需要相同的但有一个记录/复杂类型的嵌套表,用于在表中作为一行插入。

首先,我使用 oracledb 包 (v 5.1.0) 在 Node.js (TypeScript) 中有此代码:

let data: Array<DataModel>;

// data's variable is populated with data and 'DataModel' is an interface,// data is an array with a the exact table's structure: 
// [ 
//     { C_ONE: 'mike',C_TWO: 'hugman',C_THREE: '34',... with other 12 columns },//     { C_ONE: 'robert',C_TWO: 'zuck',//     { C_ONE: 'john',C_TWO: 'gates',... with other 12 columns } 
// ]

let context;

try {
    
    context = await oracledb.getConnection({
        user: 'admin',password: 'admin',connectString: 'blabla'
    });

    const result = await context.execute(
        // My SP
        'BEGIN PACKAGE_TEST.SP_TEST_STRESS(:p_data,:p_status); END;',{
            // My JSON Array
            p_data: {
                type: 'PACKAGE_TEST.T_STRESS',val: data
            },// Variable for check if all success or fails... this doesn't matters :)
            p_status: {
                type: oracledb.NUMBER,val: 1,dir: oracledb.BIND_OUT
            }
        },{ autoCommit: true }
    );

    console.log(result);

    if ((result.outBinds as { p_status: number }).p_status === 0) {
        // Correct
    }
    else {
        // Failed
    }

} catch (error) {
    
    // bla bla for errors

} finally {

    if (context) {
        
        try {

            await context.close();
            
        } catch (error) {

            // bla bla for errors

        }

    }

}

以及我的 sotore 过程的 PL/SQL 代码:

CREATE OR REPLACE PACKAGE PACKAGE_TEST
IS
    
    TYPE R_STRESS IS RECORD
    (
        C_ONE VARCHAR(50),C_TWO VARCHAR(500),C_THREE VARCHAR(10),C_FOUR VARCHAR(100),C_FIVE VARCHAR(10),C_SIX VARCHAR(100),C_SEVEN VARCHAR(50),C_EIGHT VARCHAR(50),C_NINE VARCHAR(50),C_TEN VARCHAR(50),C_ELEVEN VARCHAR(50),C_TWELVE VARCHAR(50),C_THIRTEEN VARCHAR(300),C_FOURTEEN VARCHAR(100),C_FIVETEEN VARCHAR(300),C_SIXTEEN VARCHAR(50)
    );
    
    TYPE T_STRESS IS VARRAY(213627) OF R_STRESS;
    
    PROCEDURE SP_TEST_STRESS
    (
        P_DATA_FOR_PROCESS T_STRESS,P_STATUS OUT NUMBER
    );
    
END;

/

CREATE OR REPLACE PACKAGE BODY PACKAGE_TEST
IS

    PROCEDURE SP_TEST_STRESS
    (
        P_DATA_FOR_PROCESS T_STRESS,P_STATUS OUT NUMBER
    )
    IS
    BEGIN
    
        DBMS_OUTPUT.put_line('started');
        
        BEGIN
        
            FORALL i IN 1 .. P_DATA_FOR_PROCESS.COUNT
        
                INSERT INTO TEST_STRESS
                (
                    C_ONE,C_TWO,C_THREE,C_FOUR,C_FIVE,C_SIX,C_SEVEN,C_EIGHT,C_NINE,C_TEN,C_ELEVEN,C_TWELVE,C_THIRTEEN,C_FOURTEEN,C_FIVETEEN,C_SIXTEEN
                )
                VALUES
                (
                    P_DATA_FOR_PROCESS(i).C_ONE,P_DATA_FOR_PROCESS(i).C_TWO,P_DATA_FOR_PROCESS(i).C_THREE,P_DATA_FOR_PROCESS(i).C_FOUR,P_DATA_FOR_PROCESS(i).C_FIVE,P_DATA_FOR_PROCESS(i).C_SIX,P_DATA_FOR_PROCESS(i).C_SEVEN,P_DATA_FOR_PROCESS(i).C_EIGHT,P_DATA_FOR_PROCESS(i).C_NINE,P_DATA_FOR_PROCESS(i).C_TEN,P_DATA_FOR_PROCESS(i).C_ELEVEN,P_DATA_FOR_PROCESS(i).C_TWELVE,P_DATA_FOR_PROCESS(i).C_THIRTEEN,P_DATA_FOR_PROCESS(i).C_FOURTEEN,P_DATA_FOR_PROCESS(i).C_FIVETEEN,P_DATA_FOR_PROCESS(i).C_SIXTEEN
                );
        
        EXCEPTION
        WHEN OTHERS THEN
            p_status := 1;
        END;
        
        P_STATUS := 0;
        
    END;

END;

还有我的目标表:

CREATE TABLE TEST_STRESS
(
    C_ONE VARCHAR(50),C_SIXTEEN VARCHAR(50)
);

在这种情况下会发生有趣的行为:

  • 如果我发送包含 200 行的 JSON 数组,则效果很好,我不知道成功完成所需的确切时间,但是 我可以说是毫秒。

  • 如果我发送包含 200,000 行的 JSON 数组,这需要三到四分钟的等待时间,promise 得到解决并抛出一个类型的异常:ORA-04036:实例超过 PGA_AGGREGATE_LIMIT

enter image description here

这个是在将JSON数组传递给procedure参数的时候出现的,看来处理的时候开销太大了。

  • 为什么在第二种情况下会发生这种情况?
  • 是否有限制 NESTED TABLE TYPES 中的行数还是Node.js 的任何配置(默认)?
  • Oracle 建议 增加 pga_aggregate_limit 但在我的 SQLDeveloper 中看到它 "show parameter pga;" 是3G,是不是表示我的信息 发送是否超过 3 GB?正常吗?
  • 是否有更可行的解决方案 不影响数据库的性能?

感谢您的帮助。

解决方法

每个服务器进程都有自己的 PGA,所以我猜这会导致当前运行的所有进程的总聚合 PGA 超过 3 GB。

我认为这是因为您的包裹内部发生了什么,但您只显示了规范,因此无法判断那里发生了什么。

您没有使用嵌套表类型。您正在使用 varray。 varray 的 maximum length 为 2,147,483,647。

听起来您在程序内部执行了一些操作以使用过多内存。也许您需要分块处理 200,000 行?如果没有关于您要执行的操作的更多信息,您是否可以使用其他一些进程来加载数据,例如 sqlldr?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-