database - 具有结构类型的平面数据与文档存储
问题描述
我知道这是一个“软”问题,通常不赞成 SO,但我一直在使用 BigQuery 对包含结构和重复数据的(显然)平面数据进行数据分析。让我们使用一个非常基本的示例,一行可能如下所示:
- ID
- 标题 (
str
) - 发布年份 (
int
) - 流派 (
str[]
) - 学分 (
struct[]
)
一个示例数据可能如下所示:
{
"ID": "T-1997",
"Title": "Titanic",
"ReleaseYear": 1997,
"Genres": ["Drama", "Romance"],
"Credits": {
"Actors": ["Leonardo DiCaprio", "Kate Winslet"],
"Directors": ["James Cameron"]
}
}
我的问题基本上是在原生文档存储(例如 MongoDB 或 CouchBase)中可以完成哪些类型的操作或查询,而在支持任意嵌套数据的关系数据库中则无法完成。换句话说,我的假设(我希望我是错的或被误导的)是只要数据库支持结构,它就可以做文档存储可以做的所有事情。如果不是,那么它在哪些地方:(1)可以在 MongoDB(或任何其他文档存储)中完成而在 BigQuery(或任何其他支持结构的数据库)中无法完成的事情?(2)在 MongoDB 中比在关系数据库中更容易完成的事情?
解决方案
哪些类型的操作或查询可以在原生文档存储(例如 MongoDB 或 CouchBase)中完成,而在支持任意嵌套数据的关系数据库中无法完成。
即使支持任意嵌套数据,BigQuery 与 MongoDB 相比也允许有限的嵌套。MongoDB 支持更多级别的嵌套。在 BigQuery 中,您的架构不能包含超过 15 层的嵌套 STRUCT。MongoDB 支持 BSON 文档的 100 级嵌套。
换句话说,我的假设(我希望我是错的或被误导的)是只要数据库支持结构,它就可以做文档存储可以做的所有事情。
不完全是 - 嵌套列是列中的列。但与 Mongo 这样的 NoSQL 数据库相比,RDBMS 中的分片是一项复杂的工作。从技术上讲你可以做到,但它不是为同样的目的而设计的。就像用扳手当锤子一样——当然可以,但它的目的是不同的。您应该为正确的目的使用正确的工具。
如果不是,那么它在哪些地方:(1)可以在 MongoDB(或任何其他文档存储)中完成而在 BigQuery(或任何其他支持结构的数据库)中无法完成的事情?(2) 在 MongoDB 中比在关系数据库中更容易完成的事情?
问题的症结在于,RDBMS 可能会添加一些功能以“技术上”允许您做一些您可以在 NoSQL 数据库中做的事情。但这并不意味着它可能同样有效。例如,由于使 RDBMS 成为 RDBMS 的特性(ACID 合规性、事务等),与 NoSQL 数据库相比,总会有额外的性能损失。如果 RDBMS 删除了这些特性,那么它就不再是 RDBMS!
这个答案说明了 MongoDB 如何获得更好的性能,因为它不需要支持 RDBMS 功能:
- MongoDB 每个查询的延迟更低,每个查询花费的 CPU 时间也更少,因为它做的工作少得多(例如,没有连接、事务)。
- 因此,它可以处理更高的每秒查询负载,因此如果您拥有大量用户,则经常使用它。
- MongoDB 更容易分片(在集群中使用),因为它不必担心事务和一致性。- MongoDB 具有更快的写入速度,因为它不必担心事务或回滚(因此不必担心锁定)。
- 如果您有可以利用它的特殊用例,MongoDB 没有模式。
另一个特性是分片 - 使用 mongodb 分片更容易,因为它不需要支持许多使 RDBMS 成为 RDBMS 的特性,例如符合 ACID。相比之下,RDBMS 的分片是复杂的,因为 RDBMS 必须保持 ACID 兼容。
看看以下两张图片:
快艇在水中的性能是“水陆两用车”的 10/10 倍。水陆两用车在技术上可以在水中航行,但它并非设计用于,因此速度较慢且不适合其用途。
同样,看看快艇和这辆可爱的汽车在空气动力学方面的差异。即使你把轮子钉在船上,它在陆地上的表现也不会像这辆车那样好。(打个比方,你可以说 NoSQL 数据库不进行连接 - 你必须自己实现它们。 - 但它会比 RDBMS 执行连接繁重的操作更好吗?)
我用类比来说明的一点是,每种数据库最初都是为特定目标设计的,随着时间的推移,已经添加了一些特性来尝试解决它不是为它设计的问题(因此它不起作用它以及专门为此目的设计的东西)。
因此,在您的问题中,即使 BigQuery 或某些 RDBMS可以做某事,也不意味着您应该使用它们来完成这项工作。这同样适用于 NoSQL 数据库。你应该使用最好的工具来完成这项工作。
推荐阅读
- scala - 如何使用 Taurus Blazer 为每个并发用户创建不同的用户 ID 以运行 Gatling 测试计划
- html - svg 拉伸以填充宽度,改为添加边距
- ios - iOS BluetoothManager Private API 无法附加到蓝牙守护进程
- azure-devops - 是否可以向 DevOps 实例上的所有用户广播消息或电子邮件(与管道无关)
- r - 如何让 Shiny App 动态更改数据集
- bash - bash case 语句引用的行为与记录相同,但请解释
- arrays - 我有一些在 <> 中的字符串数据,我想将其转换为列表
- r - 如何使用 ggplot 有条件地在美国地图上着色?
- visual-studio-2022 - 如何修复 VS2022 预览版的更新 4 升级“C++/WinRT”
- typescript - 打字稿:强制键和值属于同一类型?