在啥时候将大量结构化数据存储为 BLOB 才有意义?

Posted

技术标签:

【中文标题】在啥时候将大量结构化数据存储为 BLOB 才有意义?【英文标题】:At which point does storing a large amount of structured data as BLOB make sense?在什么时候将大量结构化数据存储为 BLOB 才有意义? 【发布时间】:2021-12-27 00:45:52 【问题描述】:

我们正在运行一个用于数据分析的数据库支持的 Web 应用程序,目前基于 C#.NET,服务器上带有 EntityFramework,客户端主要是 html+javascript 框架(基于 Web)。

我们的应用程序会定期接收由用户上传或由其他基础设施接收的大量批量测量 X/Y 数据点,即 1e6 或更多。

目前我们在 MSSQL 中有一个名为 Valuesid, series_id as int; x, y, z as float 的表。该表是BULK INSERT,客户端上传时填充了数据,相关元数据保存在Series 表中。 db 总大小目前接近 1TB,其中 99.99% 为Values 数据。

这种方法实现起来很简单,但它有几个缺点,随着时间的推移,它变得复杂且缓慢:

我们必须以块的形式插入,以免对它进行预处理的 IIS 进程过载(目前每个块有 200'000 个数据点) 在 INSERT 期间 IIS 进程内存需求巨大(>1500MB 用于 200MB 数据) 插入速度太慢(500 万条记录相当于 100MB,即使使用 BULK INSERT 也需要 >30 秒才能插入) 在 INSERT 期间,整个表被锁定,即一次只能插入一个用户 检索数据也很慢,请求 1e6 条记录有时需要 >10 秒 删除具有 >1e6 条记录的系列经常会导致 Web 应用端超时。

数据永远不会被部分选择,所以我们真的不需要将它放在一个表中。但它在发送给客户端之前被“精简”显示,即 1e6 条记录 - 默认情况下,即在 99% 的用例中 - 在发送给客户端之前减少到 2000 或 10'000 条记录。这被缓存在客户端上,但如果新客户端请求相同的集合,则会再次对其进行处理。 Values 表在series_id 上也有一个索引,它比表本身占用更多的磁盘空间。

我想知道将这种存储格式更改为具有自己的数据格式(CSV 或 JSON 或二进制)的“值”中的 BLOB 存储是否有意义,并且 - 也许 - 具有预处理“缩减”数据集的附加列可以在不改变的情况下推送到客户端的显示(例如,在 JSON 中)。所以新的Values 表格格式类似于

id, series_id, data(blob), reduced_data(blob)

每个Series 条目只有一个Value,而不是1e6 或更多。收到上传的数据时会创建一次缩减的数据集,然后在客户端请求时用于显示

我将丢失通过 ID 或 X/Y 值选择的 values 的部分选择,但绝不会根据 idseries_id 以外的任何内容选择值,因此这是当前不是局限性。所以这是我的问题:

这有意义吗?我希望创建和删除大型 BLOB 数据集总是比创建和删除 1,000,000 条记录要快得多。是吗? 二进制 BLOB 还是 CSV/JSON/.. BLOB? BLOB 存储的最简单方法当然是创建一个巨大的 CSV 或 JSON 块并将其保存(可能是压缩的)在数据库中。自定义二进制数据格式会更小,但必须先转换为 JSON,然后才能发送给客户端。

我觉得二进制数据格式带来的额外麻烦可能不值得,而且最好是压缩 CSV/JSON blob,而不是发明二进制格式。是吗?

我什至可能不知道的 BLOB 的其他缺点如何?大小限制似乎不是问题,varbinary(MAX) 就足够了。我不需要对 blob inside 的值的索引,只需在元数据(在 Series 表中)上。

想法?

【问题讨论】:

旁白:你不应该将你的表命名为Values,因为这是一个保留关键字(source 是的。或者User,或者... :-) 实际上,我没有。但是 a) 我很懒, b) 真实的表名会泄露有关我们应用程序的信息,这可能是超级机密的公司机密信息,你知道的。 【参考方案1】:

在 DB 中存储文件的主要优势之一是 DB 中的ACID(原子性、一致性、隔离性、持久性)技术。这使我们能够在处理数据时安全地将所有数据插入到不同的表中。当您将文件作为 BLOB 存储在 DB 中时,您在将文件复制到其他存储时具有优势,因为 BLOB 比操作文件系统更快,并且您可以轻松备份文件。但是,如果每条记录的文件大小超过 10-50-100 MB,则不建议将文件存储在 BLOB 中。在这种情况下,向表中插入记录的持续时间可能需要 10-15-30 秒。不是很好,因为事务也持续这么久,而且事务过程中的所有表在这个意义上都被阻塞了,而这些表的长时间阻塞也会导致用户无法工作。 将文件存储为 BLOB 的有趣方式之一是 FILESTREAM BLOB 技术,该技术仅受 SQL Server 支持。您可以从this

获取有关此技术的更多信息

【讨论】:

感谢您的指点。我将多个 50MB 数据块的 INSERT 基准测试到我们生产服务器上的示例表中,每个需要 1-2 秒,这是可以接受的。但是 FILESTREAM BLOB 也是一个好主意。

以上是关于在啥时候将大量结构化数据存储为 BLOB 才有意义?的主要内容,如果未能解决你的问题,请参考以下文章

什么时候使用没有 typedef 的结构有意义?

当用户群沉迷于电子表格时,啥 UI 设计才有意义

在啥情况下使用八进制?

将存储库模式与文档数据库一起使用是不是有意义?

c++ 指针参数:创建指向值的副本是不是有意义,然后再次将副本存储为指针?

Mysql的InnoDB存储引擎中的B+树索引