【问题标题】:Indexing on only part of a field in MongoDB仅对 MongoDB 中的部分字段进行索引
【发布时间】:2012-09-22 00:19:10
【问题描述】:

有没有办法只在 MongoDB 中的部分字段上创建索引,例如在前 10 个字符上?我找不到它的文档(或在此处询问)。

MySQL 等价物是 CREATE INDEX part_of_name ON customer (name(10));

原因:我有一个包含单个字段的集合,该字段的长度从几个字符到 1000 多个字符不等,平均 50 个字符。由于有大约一亿个文档,因此很难将完整的索引放入内存中(根据统计数据,使用 8% 的数据进行测试,索引已经是 400MB)。仅对字段的第一部分进行索引将使索引大小减少约 75%。在大多数情况下,搜索词很短,不是全文搜索。

解决方法是为每个项目添加 10 个(小写)字符的第二个字段,为其编制索引,然后添加逻辑以在搜索词超过 10 个字符时过滤结果(以及该额外字段 is probably needed anyway对于不区分大小写的搜索,除非有人有更好的方法)。不过,这似乎是一种丑陋的做法。

[稍后添加]

我尝试添加第二个字段,其中包含来自主字段的前 12 个字符,小写。这不是一个很大的成功。

以前,平均对象大小为 50 字节,但我忘了包括 _id 和其他开销,所以我的主要字段长度(只有一个)平均接近 30 字节而不是 50。然后,第二个字段索引包含_id 和其他开销。

净结果(对于我的 8% 样本)是主字段上的索引是 415MB,而 12 字节字段上的索引是 330MB - 只节省了 20% 的空间,不值得。我可以复制整个字段(以解决不区分大小写的搜索问题),但实际上我应该重新考虑 MongoDB 是否适合这项工作(或者只是购买更多内存并使用两倍的磁盘空间)。

[后来添加]

这是一个典型的文档,包含源字段和短小写的字段:

{ "_id" : ObjectId("505d0e89f56588f20f000041"), "q" : "Continental Airlines", "f" : "continental " }

索引:

db.test.ensureIndex({q:1});

db.test.ensureIndex({f:1});

在较短的字段上工作的“f”索引是“q”索引大小的 80%。我并不是要暗示我在索引中包含了 _id,只是它需要使用它在某个地方显示索引将指向的位置,因此这是一种开销,可能有助于解释为什么较短的键没有什么区别。

对索引的访问基本上是随机的,它的任何部分都比其他任何部分更有可能被访问。完整文件的总索引大小可能为 5GB,因此对于该索引来说并不是极端的。为其他搜索案例添加一些其他字段,以及它们的相关索引,以及小写的数据副本,确实开始加起来,并使分页和交换更有可能(它是一个 8GB 服务器),这就是我开始研究更多简洁的索引。

【问题讨论】:

  • FWIW,您可能会使用 Solr 之类的东西进行文本搜索;我将它与 MongoDB 一起使用来进行文档搜索,而且效果很好。我让 Solr 擅长它擅长的事情,让 Mongo 擅长它擅长的事情。
  • 是的,克里斯,这就是我关于重新考虑 Mongo 是否是适合这项工作的工具的评论的意思 - Mongo 没有问题(加载和索引真的很快!),只是这不是什么它非常适合(尤其是当我添加更复杂的搜索时)。 Elasticsearch 位居榜首。
  • 8GB 可能无法满足此用例的需求,除非您打算使用外部文本引擎。你说得对:全文搜索目前还不是 MongoDB 的强项之一。

标签: mongodb indexing


【解决方案1】:

MongoDB 无法在字段值的一部分上创建索引。正如您所建议的,您最好的方法是创建第二个字段。

由于无论如何您都需要第二个字段来进行不区分大小写的高效搜索,因此没有理由不创建它。

索引不存储文档的 '_id' 字段,它们存储的是 DiscLoc 结构,这是一个低级得多的结构:请参阅此处了解详细信息

另外,请注意,“丑”实际上是“关系思维”的产物。 (作为一个长期使用 SQL 的人,我经常发现学习 MongoDB 最困难的部分是un——学习我的关系思维。)在面向文档的数据库中,非规范化和复制数据实际上是最好的实践。

【讨论】:

  • 我现在尝试添加第二个字段,其中包含主字段的前 12 个字符,小写。无法将结果放入此处(没有意识到有限制),所以我将编辑问题。
  • 第二个字段索引不应包含 _id ,除非您使用它进行搜索。您的确切 ensure_index() 命令是什么?示例文档中有什么?您正在运行什么查询?
  • 另外:请注意,您不需要在内存中拥有完整的索引:只需工作集即可。您的应用程序会在整个集合中进行随机访问,还是会存在数据局部性?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-03
  • 1970-01-01
  • 2013-02-11
  • 2016-08-03
相关资源
最近更新 更多