MongoDB + C#:未选择/使用 GUID 字段上的复合索引

Posted

技术标签:

【中文标题】MongoDB + C#:未选择/使用 GUID 字段上的复合索引【英文标题】:MongoDB + C#: Compound Indexes on GUID fields not being chosen/used 【发布时间】:2015-08-30 13:47:56 【问题描述】:

在了解了有关索引如何在 MongDB 上工作的更多信息后,我决定改进一个查询,该查询在几个月内将在我目前正在处理的项目中非常有用。基本上集合有这样的结构:


   _id: UUID("0f8fad5b-d9cb-469f-a165-70867728950e"),
   Title: "ABC",
   BookId: UUID("7c9e6679-7425-40de-944b-e07fc1f90ae7"),
   UserId: UUID("7c9e6579-7425-40de-944b-e07fc1f90az9"),
   ModificationDate: ISODATE(...),
   ...
   ...

查询主要有以下两种格式:

该应用仅使用 BookId 和 UserId 进行过滤

db.userBooks.find(BookId: UUID("7c9e6679-7425-40de-944b-e07fc1f90ae7"), UserId: UUID("7c9e6579-7425-40de-944b-e07fc1f90az9"));

应用现在正在使用 BookId、UserId 和 ModificationDate 进行过滤

db.userBooks.find(BookId: UUID("7c9e6679-7425-40de-944b-e07fc1f90ae7"), UserId: UUID("7c9e6579-7425-40de-944b-e07fc1f90az9"), ModificationDate: $qt: "2015-08-30: 10:25:00.100);

对于这种情况,我在我的收藏中创建了一个这样的索引:

db.UserBooks.createIndex(BookId: 1, UserId: 1, ModificationDate: -1)

之后,我使用 BookId 和 UserId 在 Mongo Shell 上使用 explain() 运行了一个查询,令我惊讶的是,没有使用新索引!我现在不在工作,所以我不能在这里发布可解释的结果,但我可以说它对 20.000 个键和文档进行了 COLLSCAN!

我试图在网上寻找答案,但找不到太多东西。我发现 MongoDB 不适用于 GUID 类型。这提出了几个问题:

1:MongoDB 真的不“喜欢” GUID?

2:按升序或降序排列 GUID 类型没有“意义”。因此,当我在这些类型上创建索引时,我应该始终指定 1:升序吗?有关系吗?

3:在 Mongo Shell 上查询具有 GUID 的集合时,它们显示为 BinaryData(hash)。为什么?

这个特定的应用程序有一个 SQL Server 数据库。当我们有突变数据或需要非常快速的访问时,我们会在某些情况下使用 MongoDB。这些 GUID 类型是 SQL Server 数据库中的 Id。有谁知道如何解决这个问题?或者给我指个方向?

【问题讨论】:

1.不能这么说,但 GUID 被解释为二进制数据(如二进制数组)。 2.无所谓。 3. 见 1. 对于键是 ObjectId/String 的首选用法(您可以根据 Guid 生成器为字符串制作自定义生成器)。但根据我的经验,Guid 键在索引中效果很好。您确定索引是在查询运行时创建的吗(不要选中“在后台创建”以确保这一点)。 我可以将 BookId 和 UserId 更改为字符串,但 _id 没有。假设它是一个已经投入生产的应用程序,更改 _id 的类型会导致几个问题。并且需要重构应用程序逻辑。我将把查询中的参数更改为字符串来进行这个测试,看看会发生什么。 我尝试在查询此类索引(使用 GUID)时检查我的查询格式并为您提供更多信息。正如我所说的那样,“引导式”索引效果很好。 我看到 MongoDb 的 C# 驱动程序为查询表示中的 GUID 生成,例如“new BinData(3,"")”。正如我看到的那样执行使用我的索引(包含 Guid 和 Int64 字段)。但是当我使用 UUID 格式运行它时,它也可以很好地使用索引。 是的,MongoDb C# 驱动似乎支持它。 ***.com/questions/13254784/… 但是我使用 MongoVUE 进行查询测试 【参考方案1】:
    因此 MongoDb 使用 GUID 并将它们解释为 UUID 数据格式(所谓的 BinData)。如需更多信息,请参阅:http://docs.mongodb.org/manual/reference/bson-types/ 和 http://docs.mongodb.org/manual/reference/method/UUID/ 在实践中,我从未见过 GUID 索引的顺序很重要的情况,因此默认情况下您可以使用升序。 请参阅第 1 页,如文档中所述 - GUID 在 MongoDb BSON 类型系统中确实是 BinData 格式。因此,唯一的字符串或 ObjectId 是用作主键 (_id) 的引用类型。 因此,我们在 cmets 对话期间取得了成果 - 复合(多字段)索引与 C# 驱动程序查询配合得很好。

【讨论】:

以上是关于MongoDB + C#:未选择/使用 GUID 字段上的复合索引的主要内容,如果未能解决你的问题,请参考以下文章

使用C#开发ActiveX控件

如何使用 MongoDB 以编程方式预拆分基于 GUID 的分片键

C# GUID的使用

Mongodb中GUID的显示问题

guid的值为null如何在C#反序列化

获取使用大端格式 C# 进行编码的 guid