c# - MongoDB数据建模——索引和PK

标签 c# mongodb data-modeling nosql

我目前正在从 RDBMS 过渡到 NoSQL 解决方案,更具体地说是 MongoDB。考虑我的数据库中的下表(原始解决方案要复杂得多,但我将其包括在内以便您有一个想法):

  • 用户(PK_ID_User、名字、姓氏...);
  • 用户配置文件:(PK_ID_UserProfile、ProfileName、FK_ID_User、...);

此表中的键是 GUID,但它们是自定义生成的。例如:

  • UserGUID 将具有以下结构:US022d717e507f40a6b9551f11ebf2fcb4(因此,美国前缀和随机数), 而 UserProfile GUIDS 将采用以下格式:UP0025f5804a30483b9b769c5707b02af6(因此 UP 前缀和随机数)

现在,假设我想将此 RDBMS 数据模型转换为 NoSQL MongoDB。对于我的应用程序(使用 C# 驱动程序),MongoDB 中的所有文档属性都具有相同的名称非常重要。这对于 ID 字段也很重要:名称 PK_ID_User 和 PK_ID_UserProfile,包括 GUID,必须相同。

现在,MongoDB 使用标准的唯一索引属性 _id 来存储 ID。这个 _id 字段的名称当然不能更改,即使我确实需要我的应用程序保留列/属性名称。

因此,我为我的用户和用户配置文件提出了以下文档结构。请记住,对于这种情况,我选择使用引用数据建模而不是嵌入,原因多种多样,我不会在这里解释: 用户文档

{
_id: ObjectId, - indexed
PK_ID_User: custom GUID, - indexed, as it needs to be unique
FirstName: string,
...
}
UserProfile-document
{
_id: ObjectId - indexed
PK_ID_UserProfile: custom GUID, as explained above - indexed, as it needs to be unique,
...
}

这是 C# 类:

  public class User
  {
    [BsonConstructor]
    public User() { }

    [BsonId] // the _id field
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }

    [BsonElement("PK_ID_User")]
    public string PK_ID_User { get; set; }

    //Other Mapper properties
  }

我选择这种建模策略的原因如下:当前项目包含一个完整的 Web 服务,使用 ORM 和 RDBMS,以及一个或多或少将数据库对象映射到客户端 View 对象的客户端。因此,确实有必要尽可能多地保留 ID/PK 的名称。我决定最好让 MongoDB 在内部使用 ObjectId(用于 CRUD 操作),因为它们不会导致性能开销,并使用自定义 GUID,以便它们与我的其余代码兼容。这样,只需进行最少的更改,MongoDB 很高兴,我也很高兴,因为在外部,我可以根据始终唯一的 GUID PK 继续查询结果。 与在 MongoDB 中一样,我的 PK GUID 存储为唯一字符串,我想我不必担心服务器端的 GUID 开销:GUID 是由我的 C# 应用程序创建的。

但是,我对性能有疑问,我现在每个文档/集合至少有 2 个索引,并且不知道它在性能方面的成本有多大。

是否有更好的方法来解决我的问题,还是我应该坚持目前的解决方案?

亲切的问候。

最佳答案

I now always have a minimum of 2 indexes per document / collection, and have no idea how costly it is in terms of performance.

索引会降低插入和更新的性能,并且您没有发布有关写入操作频率或您的设置的信息。没有测量就不可能给出明确的答案。

然后,如果您使用的是 Web 应用程序,我想说您的客户端的纯粹网络延迟将比 1、2 或 3 之间的差异高几个数量级索引,因为所有这些操作大部分都会访问 RAM。

代价高昂的是写入磁盘,而不是在内存中重构 BTree。当然,拥有越来越多的索引会增加插入操作的可能性,从而导致必须对磁盘进行昂贵的索引树重组,但这也取决于键本身的结构。

如果有的话,我会担心 GUID 的缓存一致性和时间局部性不好:如果您的数据非常具有时间局部性(如日志),那么 GUID 可能会受到伤害(字符串开头的高抖动),因为更新更有可能重新排列整个子树,而典型的时间范围查询会抓取整个树中杂乱无章的项目。但由于这似乎与用户和用户个人资料有关,因此这样的查询可能没有多大意义。

关于c# - MongoDB数据建模——索引和PK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28960272/

相关文章:

c# - 如何调试动态工作流(使用自定义事件)

c# - 如何在 javascript 中实现 C# 访问修饰符?

mongodb - 查找给定的经纬度是否位于 MongoDB 中的任何多边形中

mongodb - ReactiveMongoRepository/MongoRepository不返回_id字段

node.js - MongoDB:$and 运算符无法使用 Node.JS 驱动程序进行批量更新

mysql - 将多个数据存储到一个字段中以便更好地管理?

domain-driven-design - 数据建模和领域建模有什么区别?

c# - 保存发送给机器人的用户消息并将完成的表格发送给其他用户

c# - 使用 AutoMapper 强制浅拷贝

php - 多对多关系数据库的复合FK表