如何有效地将大文件加载到 IndexedDB 存储中?我的应用程序在超过 100,000 行时崩溃

Posted

技术标签:

【中文标题】如何有效地将大文件加载到 IndexedDB 存储中?我的应用程序在超过 100,000 行时崩溃【英文标题】:How to efficiently load large files into IndexedDB storage? My app is crashing at over 100,000 rows 【发布时间】:2019-06-03 16:25:25 【问题描述】:

我有一个特定的 Web 应用程序,它依赖于从客户端的本地文件上传大量数据行。目的是将这些数据存储在 indexeddb 中。

数据只有两列我感兴趣,每列包含不超过 25 个字符的字符串,但最多可以有 100 万行。

阅读了很多问题和文档,我创建了一些代码,这些代码似乎适用于创建具有 20,000 行以下的较小数据集的 indexeddb,但会在较大的数据上中断。

我确定这是由于设计不佳,因为我是这种工作风格的新手,或者可能在 chrome 浏览器中出现某种冻结 - 因为我没有收到任何错误消息,所以我可以触发到达最后一个 for 循环的警报,但是 on.complete 永远不会触发,并且数据库似乎永远不会

函数 e - 的输入是一个读取文件。

我还在 for 循环中对数据执行了操作,但为简单起见,我已将其删除。

function storeDataEnc (e) 
    var lines = e.target.result.split('\n');
    var request = self.indexedDB.open('DB', 1);
    request.onerror = function(e) 
        console.log("there was and error:" +e.target.errorCode);
    
    request.onupgradeneeded = function(e)
        var db = request.result;
        var store = db.createObjectStore("col1", 
                    keyPath: "col2" );
    ;

    request.onsuccess = function(e) 

        var db = request.result;
        var tx = db.transaction("dataTable", "readwrite");

        var store = tx.objectStore("dataTable");

        db.onerror = function(e)
            console.log("ERROR" + e.target.errorCode);
        


    for (var i = 0; i < lines.length; ++i) 
        var test = lines.length - 1;
        if (i == test) console.log('nearly done');

            function forEachLinenow (match) 
                if ( match.charAt( 0 ) != '#' ) 
                    match = match.trim();
                    var fields = match.split('\t');
                    var col1in = fields[0];
                    var col2in = fields[3];

                    store.put( COL1: col1in, COL2: col2in              
            
        forEachLinenow(lines[i] + '\n');
    
    tx.oncomplete = function() 
            db.close();
            alert("all data read");
        
    

我猜我不了解浏览器的某些问题,以阻止恶意应用占用过多资源。有没有人使用过这种大小的数据,谁能发现我的过程中的错误。

我的猜测是我可能需要生成多个交易,我确实尝试过,但似乎并没有改变我的问题。

我知道这可能会很慢,但是只要数据成功导入,速度本身并不是最大的问题。

【问题讨论】:

有一点代码味道,你肯定没有理由需要将 1M 记录加载到浏览器数据库中吗? 哈哈 这是一个小众应用程序,从用户的角度来看,它对于包括我在内的少数用户来说非常有用。最后,我可能不得不保留您可能会推荐的服务器端,但是当百万条记录只有 20MB 时,我真的认为大小问题对于小用户组的实际利益来说是非常疏忽的——尤其是考虑到可比较的说一个小视频的大小。 【参考方案1】:

您可能会达到浏览器的数据大小限制。

在 mozilla 文档中,它提到了限制 https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Browser_storage_limits_and_eviction_criteria

这里有一些更多的 indexeddb 限制,由 google 记录,用于流行的浏览器。 https://developers.google.com/web/fundamentals/instant-and-offline/web-storage/offline-for-pwa

似乎限制都是基于主机操作系统的可用存储。 检查您希望导入的数据大小和可用存储空间。

【讨论】:

看起来问题实际上是达到了数据大小限制。我没有注意到这一点,因为我预计 indexedDB 将分配 6% 的磁盘空间,如文档中所写,但是在我的 chrome 浏览器中,它最多只允许 101MB。我不确定为什么浏览器会强制执行此限制。此外,有趣的是,与文件相比,该文件在数据库中占用了更多的存储空间。这可能是个问题。 问题确实是应用程序达到了大小限制,但没有引发任何类型的错误处理事件。事实证明这是浏览器选择的问题。当我使用谷歌浏览器并期望总可用存储空间的 6% 时,我的浏览器默认为“隐身模式”,结果证明对应用程序设置了不同的硬限制。使用 Google Chrome 中的开发工具检查选项,我能够看到应用程序中每个窗口的数据限制都设置为 101MB,这是问题所在。 因此,如果其他人遇到类似的问题,这似乎是一个非常简单的浏览器选择和设置问题。确保您没有通过隐身模式运行 indexedDb 应用程序。

以上是关于如何有效地将大文件加载到 IndexedDB 存储中?我的应用程序在超过 100,000 行时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

如何有效地将大字符串从 Python 传递到 C++ 扩展方法?

如何有效地将数据从 CSV 加载到数据库中?

如何有效地将巨大的 sql 表加载到 asp.net 应用程序内存中以进一步迭代它?

如何将大文件加载到分块的 Adonis JS 中?

如何将大文件存储到 Web 本地存储?

如何避免将大文件重复加载到 python 脚本中?