仅对MongoDB中的部分字段进行索引

时间:2012-09-22 00:19:10

标签: mongodb indexing

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

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

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

解决方法是为每个项添加第二个10(小写)字符的字段,索引,然后添加逻辑以在搜索项超过10个字符时过滤结果(以及额外字段{{3对于不区分大小写的搜索,除非有人有更好的方法)。看起来似乎是一种丑陋的方式。

[稍后补充]

我尝试添加第二个字段,包含主字段中的前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的服务器),我为什么开始研究更多简明指数。

1 个答案:

答案 0 :(得分:2)

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

因为无论如何你都需要第二个字段进行有效的不区分大小写的搜索,所以没有理由不创建它。

索引不存储文档的“_id”字段,它们存储DiscLoc结构,这是一个更低级别的结构:有关详细信息,请参阅此处

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