TypeORM中出现内存问题,或者我只是将其填满

问题描述

已使用typeorm在typescript中编写了数据库初始化脚本。而且我似乎造成了内存问题,但我想不出办法解决。

当前,脚本导入了三个文件 个人资料(55条记录) 用户(5306条记录) 登录(1006909条记录)

重写调用,因此在所有情况下,脚本都会创建一个包含所有更新的JSON,然后使用createQueryBuilder来执行更新,如下所示:

getConnection()
                                    .createQueryBuilder()
                                    .insert()
                                    .into(EULogin)
                                    .values(loginChunk)
                                    .execute()
                                    .catch(error => console.log(error))

为第一个创造一个魅力,但是当涉及到最后一个(整个1,000,000个)时,它不会打球。而且我遇到了内存问题

登录:在155 MS中将196000/1006909(块大小:500)提交到数据库 登录:在823 MS中将196500/1006909(区块大小:500)提交到数据库

[60698:0x110008000] 34328 ms:清除1389.1(1423.6)-> 1388.6 (1423.6)MB,12.1 / 0.0毫秒(平均亩= 0.104,当前亩= 0.099) 分配失败[60698:0x110008000] 34339毫秒:清除1389.3 (1423.6)-> 1388.9(1423.6)MB,10.4 / 0.0毫秒(平均亩= 0.104, 当前亩= 0.099)分配失败[60698:0x110008000] 34361 毫秒:Scavenge 1389.4(1423.6)-> 1389.1(1424.1)MB,12.5 / 0.0毫秒 (平均亩= 0.104,当前亩= 0.099)分配失败

==== JS堆栈跟踪======================================== =

0: ExitFrame [pc: 0x20ed7445be3d]
1: StubFrame [pc: 0x20ed7440d608]
2: StubFrame [pc: 0x20ed7502c4cc] Security context: 0x0fbfb411e6e9 <JSObject>
3: /* anonymous */(aka /* anonymous */) [0xfbf79c62a41] [/Users/bengtbjorkberg/Development/EUGrapherNode/node_modules/typeorm/query-builder/InsertQueryBuilder.js:348]

[bytecode = 0xfbf93b851a1 offset = 26](this = 0x0fbfab4826f1 ,valueSet = 0x0fbf8846ebc1

致命错误:接近堆限制分配的无效标记压缩 失败-JavaScript堆内存不足1:0x10003cf99 node :: Abort() [/ usr / local / bin / node] 2:0x10003d1a3 node :: OnFatalError(char const *, char const *)[/ usr / local / bin / node] 3:0x1001b7835 v8 :: internal :: V8 :: FatalProcessOutOfMemory(v8 :: internal :: Isolate *,char const *,bool)[/ usr / local / bin / node] 4:0x100585682 v8 :: internal :: Heap :: FatalProcessOutOfMemory(char const *) [/ usr / local / bin / node] 5:0x100588155 v8 :: internal :: Heap :: CheckInvalidMarkCompact(无符号长整数,双精度) [/ usr / local / bin / node] 6:0x100583fff v8 :: internal :: Heap :: PerformGarbageCollection(v8 :: internal :: GarbageCollector, v8 :: GCCallbackFlags)[/ usr / local / bin / node] 7:0x1005821d4 v8 :: internal :: Heap :: CollectGarbage(v8 :: internal :: AllocationSpace, v8 :: internal :: GarbageCollectionReason,v8 :: GCCallbackFlags) [/ usr / local / bin / node] 8:0x10058ea6c v8 :: internal :: Heap :: AllocateRawWithLigthRetry(int, v8 :: internal :: AllocationSpace,v8 :: internal :: AllocationAlignment) [/ usr / local / bin / node] 9:0x10058eaef v8 :: internal :: Heap :: AllocateRawWithRetryOrFail(int, v8 :: internal :: AllocationSpace,v8 :: internal :: AllocationAlignment) [/ usr / local / bin / node] 10:0x10055e434 v8 :: internal :: Factory :: NewFillerObject(int,bool, v8 :: internal :: AllocationSpace)[/ usr / local / bin / node] 11:0x1007e6714 v8 :: internal :: Runtime_AllocateInNewSpace(int,v8 :: internal :: Object **, v8 :: internal :: Isolate *)[/ usr / local / bin / node] 12:0x20ed7445be3d

以退出代码134(被信号6:SIGABRT中断)结束的过程

我试图以同步模式(不是异步)打开数据库 我试图一次将最近的更新分成50条记录 我什至尝试打开和关闭每个块的数据库,但是死了,因为我无法使其同步执行。

使用以下方法打开数据库

createConnection().then(connection => {

下面是“ Chunkloader”

.on('end',() => {
                            let compTime: number = new Date().getTime()
                            console.log("LOGIN: Entities read: " + loginReadCounter + " in " + new Date(compTime - loginStartTime).getMilliseconds() + " MS")
                            let currentChunk :number = 0;
                            let chunkSize : number = 500;
                            let loginChunk = [];
                            let loginStartChunkTime : number = compTime;
                            loginEntries.forEach(entry => {
                                loginChunk.push(entry);
                                currentChunk ++;
                                loginCommitCounter++;
                                if (currentChunk === chunkSize !! ){
                                    getConnection()
                                        .createQueryBuilder()
                                        .insert()
                                        .into(EULogin)
                                        .values(loginChunk)
                                        .execute()
                                        .catch(error => console.log(error))

                                    let compTime: number = new Date().getTime()
                                    console.log("LOGIN: Committed "  + loginCommitCounter + "/" + loginReadCounter + " (Chunk Size:" + loginChunk.length + ") to database in " + new Date(compTime - loginStartChunkTime).getMilliseconds() + " MS");
                                    currentChunk = 0;
                                    loginStartChunkTime = compTime;
                                    loginChunk = [];

                                }
                            });

有什么想法吗?

=========================编辑好输入后================== ===

要尝试整理自己的头脑,我将其移至单独的函数中,我使await正常工作,但是如何在调用后阻止该过程继续进行。因为await在createConnection内有效,但在createConnection上无效,因此该函数将立即返回

function syncDataWrite(dbEntitiy,dataSet){
    console.log("DBLOADER Started for: " + dataSet.length);
    createConnection().then(async connection => {
        console.log("DBLOADER Connected!");
        const completion = await createQueryBuilder()
            .insert()
            .into(dbEntitiy)
            .values(dataSet)
            .execute()
            .catch(error => console.log(error))
            console.log("DBLOADER SQL uploaded")
    })
    // console.log(dbEntity);

}

解决方法

您的代码建议,在对事物进行分块处理时,您将并行执行一切,这可能不是您想要的。

我建议您重写此代码以使其正确顺序。

到目前为止,最简单的方法是切换到异步/等待并使用常规的for循环。假设.execute()返回了一个承诺,这看起来像这样:

const connection = getConnection();
for (const entry of loginEntries) {
   // [snip]  
   await createQueryBuilder()
     .insert()
     .into(EULogin)
     .values(loginChunk)
     .execute()
   // [snip]
}

我剥离了很多代码,但我希望这种常规设置仍然有意义。

无需异步/等待就可以执行此操作,但是看起来要复杂得多。

根据您的修改进行编辑

这是syncDataWrite的重写版本:

async function syncDataWrite(dbEntitiy,dataSet){

    console.log("DBLOADER Started for: " + dataSet.length);
    const connection = await createConnection();
    console.log("DBLOADER Connected!");
    const completion = await createQueryBuilder()
       .insert()
       .into(dbEntitiy)
       .values(dataSet)
       .execute();

}

请注意,如果您多次使用syncDataWrite,每个块使用1,则在调用await syncDataWrite时仍需要CREATE TABLE BASE_TABLE AS ( SELECT ACT_DESC_,QTY AS EXCAVATION_QTY,APP_DATE AS EXCAVATION_APP_DATE,DOC_NO AS EXCAVATION_DOC_NO,QTY AS FORM_WORK_COMP_QTY,APP_DATE AS FORM_WORK_COMP_APP_DATE,DOC_NO AS FORM_WORK_COMP_DOC_NO,FROM SOURCE_TABLE --this is the original table,or the table from the first image WHERE 0=1 --this clause condition is used to create an empty table );

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...