当存在大的字段组合时,在 MongoDB 中索引的正确方法是什么 [英] What is the correct way to Index in MongoDB when big combination of fields exist

查看:18
本文介绍了当存在大的字段组合时,在 MongoDB 中索引的正确方法是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑到我的搜索面板包含多个选项,如下图所示:

Considering I have search pannel that inculude multiple options like in the picture below:

我正在使用 mongo 并按特定顺序在 3-4 个属性上创建复合索引.但是当我运行不同的搜索组合时,我每次都会看到执行计划(explain())中的不同顺序.有时我在 Collection scan (bad) 上看到它,有时它正好适合索引 (IXSCAN).

I'm working with mongo and create compound index on 3-4 properties with specific order. But when i run a different combinations of searches i see every time different order in execution plan (explain()). Sometime i see it on Collection scan (bad) , and sometime it fit right to the index (IXSCAN).

mongo 索引应该处理的选择性字段是:(brand,Types,Status,Warehouse,Carries,Search - only by id)

The selective fields that should handle by mongo indexes are:(brand,Types,Status,Warehouse,Carries ,Search - only by id)

我的问题是:

我是否必须以不同顺序创建所有字段的所有组合,它可以是10-20个复合索引.或者 1-3 个大的 Compound Index ,但它又不会解决顺序.

Do I have to create all combination with all fields with different order , it can be 10-20 compound indexes. Or 1-3 big Compound Index , but again it will not solve the order.

处理大量字段组合的最佳策略是什么.

What is the best strategy to deal with big various of fields combinations.

我使用具有不同对组合的相同结构查询

I use same structure queries with different combinations of pairs

// Example Query. 
// fields could be different every time according to user select (and order) !!

 db.getCollection("orders").find({
  '$and': [
    {
      'status': {
        '$in': [
          'XXX',
          'YYY'
        ]
      }
    },
    {
      'searchId': {
        '$in': [
          '3859447'
        ]
      }
    },
    {
      'origin.brand': {
        '$in': [
          'aaaa',
          'bbbb',
          'cccc',
          'ddd',
          'eee',
          'bundle'
        ]
      }
    },
    {
      '$or': [
        {
          'origin.carries': 'YYY'
        },
        {
          'origin.carries': 'ZZZ'
        },
        {
          'origin.carries': 'WWWW'
        }
      ]
    }
  ]
}).sort({"timestamp":1})

// My compound index is:
{status:1 ,searchId:-1,origin.brand:1, origin.carries:1 , timestamp:1}

但它只有一种组合......它可能很多

but it only 1 combination ...it could be plenty like

a. {status:1} {b.status:1 ,searchId:-1} {c. status:1 ,searchId:-1,origin.brand:1} {d.status:1 ,searchId:-1,origin.brand:1, origin.carries:1} ........

此外,性能写入/读取会发生什么?,我认为写入会减少读取...

Additionally , What will happened with Performance write/read ? , I think write will decreased over reads ...

查询模式是:

1.find(...) with '$and'/'$or' + sort

2.匹配/排序聚合

谢谢

推荐答案

我注意到了这个一年前的话题,因为我或多或少都在为一个类似的问题苦苦挣扎:用户可以使用一组不可预测的字段来请求查询,这使得几乎不可能决定(或更改)应该如何定义索引.

I noticed this one-year-old topic, because I am more or less struggling with a similar issue: users can request queries with an unpredictable set of the fields, which makes it near to impossible to decide (or change) how indexes should be defined.

更糟糕的是:用户应该为组成分片键的字段指定一些值(或范围),否则我们无法帮助 MongoDB 将其搜索限制在几个分片(或块,就此而言).当用户需要自由搜索组成分片键的其他字段并不是必需的时,我们就会陷入全数据库搜索的困境.我们的数据库大约有 10 个 TB 大小......索引应该适合 RAM 吗?这只能通过小型数据库来实现,这意味着最多 100 GB.我的 37 TB 数据库怎么样?索引不适合 RAM.

Even worse: the user should indicate some value (or range) for the fields that make up the sharding-key, otherwise we cannot help MongoDB to limit its search in only a few shards (or chunks, for that matter). When the user needs the liberty to search on other fields that are not necessariy the ones which make up the sharding-key, then we're stuck with a full-database search. Our dbase is some 10's of TB size... Indexes should fit in RAM ? This can only be achieved with small databases, meaning some 100's GB max. How about my 37 TB database ? Indexes won't fit in RAM.

所以我正在尝试一个受 UNIX 文件系统结构启发的 POC,其中我们有指向数据块的 inode:

So I am trying out a POC inspired by the UNIX filesystem structures where we have inodes pointing to data blocks:

  1. 我们有一个包含 108 个分片的集群,每个分片包含 100 个块
  2. 在插入时,我们采用一些我们知道它们产生良好数据基数的字段,然后我们用这些字段计算分片键;文档进入该计算分片上的主集合(称为Main_col"),因此具有特定的块号(等于我们计算出的分片键值)
  3. 从原始文档中,我们选取​​一些关键"字段(此类字段的列表可以随着您的需求变化而变化)并将一个小的额外文档存储在另一个集合中(将这些称为Crucial_col_A"、Crucial_col_B"等,每个这样的字段一个):该文档包含这个关键字段的值,加上一个带有块号的数组,其中原始完整文档已存储在大"集合Main_col"中;将此视为指向集合Main_col"中块的指针";存在此完整文档的位置.这些Crucial_col_X"集合根据关键"字段的值进行分片.
  4. 当我们插入另一个对某些关键"字段A"具有相同值的文档时,Crucial_col_A"中的该数组将被插入.块号被更新(使用合并")以包含来自Main_col"的下一个完整文档的不同或相同块号
  5. 用户现在可以定义查询,其中至少有一个关键"字段的标准,加上(可选)文档中其他字段的任何其他标准;关键字段的第一个标准(比如字段B")将运行得非常快(因为根据B"的值进行分片)并从Crucial_col_B"返回小文档,其中我们有块数组-Main_col"中的数字其中存在具有字段B"的任何文档;等于给定的标准.然后我们运行第二组并行查询,一个针对我们之前在数组中找到的每个 shardkey-value=chunk-number(或每个分片一个,待决定).我们将这些并行子查询的结果结合起来,然后在用户提供额外条件时应用进一步的过滤.

因此这涉及 2 个查询步骤:首先在Crucial_col_X"中;集合以获取包含完整文档的块号的数组,然后在Main_col"中对这些特定块进行第二次查询.第一个查询是使用关键"字段的精确值完成的,因此确切的分片/块是已知的,因此该查询进行得非常快.第二(组)查询是使用分片键(= 块编号)的精确值完成的,因此预计这些查询也会非常快.

Thus this involves 2 query-steps: first in the "Crucial_col_X" collection to obtain the array with chunk-numbers where the full documents exist, and then the second query on those specific chunks in "Main_col". The first query is done with a precise value for the 'crucial' field, so the exact shard/chunk is known, thus this query goes very fast. The second (set of) queries are done with precise values for the sharding-keys (= the chunk numbers), so these are expected to go also very fast.

这种工作方式将消除定义许多索引组合的负担.

This way of working would eliminate the burden of defining many index combinations.

这篇关于当存在大的字段组合时,在 MongoDB 中索引的正确方法是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆