将SQL数据库转换为NoSQL数据库时的建模技巧

5

我有一个 SQL 数据库,想要转换成 NoSQL 数据库(我目前使用的是 RavenDB)。

以下是我的表:

Trace:

ID (PK, bigint, not null)
DeploymentID (FK, int, not null)
AppCode (int, not null)

部署:

DeploymentID (PK, int, not null)
DeploymentVersion (varchar(10), not null)
DeploymentName (nvarchar(max), not null)

应用:

AppID (PK, int, not null)
AppName (nvarchar(max), not null)

目前我在表中有这些行:

追踪:

ID: 1 , DeploymentID: 1, AppCode: 1
ID: 2 , DeploymentID: 1, AppCode: 2 
ID: 3 , DeploymentID: 1, AppCode: 3 
ID: 3 , DeploymentID: 2, AppCode: 1

部署:

DeploymentID: 1 , DeploymentVersion: 1.0, DeploymentName: "Test1"
DeploymentID: 2 , DeploymentVersion: 1.0, DeploymentName: "Test2"

应用:

AppID: 1 , AppName: "Test1"
AppID: 2 , AppName: "Test2"
AppID: 3 , AppName: "Test3"

我是一个有用的助手,可以为您进行翻译。
我的问题是:我该如何构建我的NoSQL文档模型?
它应该是这个样子吗:
trace/1
{
 "Deployment": [ { "DeploymentVersion": "1.0", "DeploymentName": "Test1" } ],
 "Application": "Test1"
}

trace/2
{
 "Deployment": [ { "DeploymentVersion": "1.0", "DeploymentName": "Test1" } ],
 "Application": "Test2"
}

trace/3
{
 "Deployment": [ { "DeploymentVersion": "1.0", "DeploymentName": "Test1" } ],
 "Application": "Test3"
}

trace/4    
{
 "Deployment": [ { "DeploymentVersion": "1.0", "DeploymentName": "Test2" } ],
 "Application": "Test1"
}

如果部署1发生更改怎么办?我需要逐个文档更改数据吗?

在NoSQL中何时应该使用引用?


"NoSQL"不是一个数据库,而是一个泛指不使用SQL的数据库。这包括键值存储,文档数据库,图数据库等等。如何建模数据既取决于您的用例,也取决于所使用的数据库的功能。 - Stennie
我写了,我正在使用 RavenDB,它是一个文档型数据库。 - ohadinho
2个回答

8
像Raven这样的文档数据库并不是关系型数据库。你不能先构建数据库模型,然后再决定各种有趣的查询方式。相反,你应该首先确定要支持哪些访问模式,然后相应地设计文档模式。
因此,为了回答你的问题,我们真正需要知道的是你打算如何使用数据。例如,按时间顺序显示所有跟踪信息与显示与特定部署或应用程序相关联的跟踪信息是截然不同的场景。每个需求都将指导不同的设计,支持它们也是如此。
这本身可能对你有用(?),但我怀疑你想要更具体的答案 :) 所以请添加一些关于你打算使用的其他详细信息。
在制定策略时,有一些“要做”的和“不要做”的:
要做:优化常见用例。通常会有一个20/80的分布,其中20%的UX驱动80%的负载-Web应用程序的主页/着陆页面就是一个经典的例子。首要任务是确保这些尽可能高效。确保您的数据模型允许A)在单个IO请求中加载这些或B)适合缓存
不要做:不要陷入可怕的“N + 1”陷阱。当您的数据模型强制您使N次调用以加载N个实体时,就会出现这种模式,通常是在另一个调用之前获取N个ID的列表。这是致命的,特别是与#3一起使用时...
要做:始终通过UX限制您愿意获取的数据量。如果用户有3729条评论,您显然不会一次性获取它们所有。即使从数据库角度来看是可行的,用户体验也会很糟糕。这就是为什么搜索引擎使用“下一页20个结果”的范例。因此,您可以(例如)将数据库结构与UX对齐,并将评论保存在20个块中。然后每次页面刷新都涉及单个DB获取。
要做:平衡读写要求。某些类型的系统对读取非常重要,可以假定对于每个写入操作,将有许多读取操作(StackOverflow是一个很好的例子)。因此,在读取性能方面进行写入操作更加昂贵是有意义的。例如,数据去规范化和复制。其他系统则平衡或甚至写入较重,需要采用其他方法
要做:利用时间维度。Twitter是一个经典的例子:99.99%的推文在第一个小时/天/周/任何时间之后都不会被访问。 这打开了各种有趣的优化可能性在您的数据模式中。
这只是冰山一角。我建议了解一下基于列的NoSQL系统(例如Cassandra)。

感谢您的友善回答 :) 首先,写入操作比读取操作更频繁。 其次,我需要通过日期时间快速获取一大块数据(我知道我在这里的文档中没有写出来)。 第三,通过一些关键值ID(例如:MessageId =“aaa22kk”),我想获取该消息的数据。 我知道我应该为这些读取操作建立索引,但我仍然无法弄清楚如何设计我的数据库模型。 - ohadinho
这是一种日志文档,其中有很多写入操作和一些偶尔的读取操作。 - ohadinho

1
您如何建模文档主要取决于您的应用程序及其领域。从那里开始,通过了解数据访问模式可以完善文档模型。
盲目尝试将关系数据模型映射到非关系数据模型可能不是一个好主意。
更新:我认为Matt已经理解了我的观点。我的意思是,没有预定的方法(至少我不知道)可以将关系数据模型(如规范化的SQL模式)转换为非关系数据模型(如文档模型),而不了解和考虑应用程序的领域。让我在这里详细说明一下...
在查看您的SQL模式之后,我不知道除了连接应用程序和部署的表之外,跟踪是什么。我也不知道您的应用程序通常如何查询数据。了解其中一些信息对于建模文档非常重要,就像它会影响您建模应用程序对象(或领域对象)的方式一样。
因此,您在问题中提出的文档模型可能适用于您的应用程序,也可能不适用。

那么你的意思是我应该采用我上面提出的NoSQL模型? - ohadinho
1
我认为他的意思是你应该采取面向域而不是数据的方法。 - MattDavey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接