Mongo多字段过滤器查询和排序-优化

时间:2019-04-10 15:31:41

标签: mongodb mongo-java mongodb-indexes

我有一个记录集合,其中包含primary_id(唯一),secondary_id,状态字段。 ID是字母数字字段(例如'ABCD0000'),状态是数字(1-5)。 经常使用的查询之一是按ID(相等性或范围)和状态进行过滤。

示例:

  1. 记录“ ABCD0000”-“ ABCN0000”与状态之间的primary_id为2或3的情况,并按primary_id排序。
  2. 记录“ ABCD0000”-“ ABCD0000”与状态之间的secondary_id为2或3的记录,并按primary_id排序(如果有帮助,则按secondary_id排序)。

过滤器中的状态通常为((2,3)中的状态)。

最初,我们在每个字段上都有一个索引。但是,当范围较大时,查询会超时。我尝试添加多个索引(单个和复合),并以不同的方式编写过滤器,但性能不佳。现在我有了这些索引:

[
{primary_id: 1},
{secondary_id: 1},
{status: 1},
{primary_id: 1, status: 1},
{status: 1, primary_id: 1},
{status: 1, secondary_id: 1}
]

此查询(对primary_id进行排序或不进行排序)

{ $and: [ 
{ primary_id: { $gte: 'ABCD0000' } }, 
{ primary_id: { $lte: 'ABCN0000' } }, 
{status: { $in: [2,3] } } 
] }

使用以下计划:

...
"winningPlan" : {
    "stage" : "FETCH",
    "filter" : {
            "status" : {
                    "$in" : [
                            2,
                            3
                    ]
            }
    },
    "inputStage" : {
            "stage" : "IXSCAN",
            "keyPattern" : {
                    "primary_id" : 1
            },
            "indexName" : "primary_idx",
            "isMultiKey" : false,
            "multiKeyPaths" : {
                    "primary_id" : [ ]
            },
            "isUnique" : true,
            "isSparse" : false,
            "isPartial" : false,
            "indexVersion" : 2,
            "direction" : "forward",
            "indexBounds" : {
                    "primary_id" : [
                            "[\"ABCD0000\", \"ABCN0000\"]"
                    ]
            }
    }
},

因此,如果返回的行数很大,似乎FETCH步骤会花费很长时间。出乎意料的是,在运行初始测试时,有时会选择primary_id复合索引作为获胜计划,而且速度超快(几秒钟)。但是由于某种原因,Mongo不再选择它了。我猜想当查询需要按primary_id排序时,根据我从Mongo文档中了解到的那样,不会选择此复合索引

  

如果查询未在排序规范之前或与之重叠的索引前缀上指定相等条件,则该操作将无法有效使用索引。

我尝试按以下方式更改查询,但仍未优化

{$or: [
{ $and: [ { primary_id: { $gte: 'ABCD0000' } }, { primary_id: { $lte: 'ABCN0000' } }, { status: 2 } ]},
{ $and: [ { primary_id: { $gte: 'ABCD0000' } }, { primary_id: { $lte: 'ABCN0000' } }, { status: 3 } ]}
]}

关于什么是更好的索引或查询策略的任何建议?

1 个答案:

答案 0 :(得分:0)

我会尝试2个索引

primary_id(状态)和secondary_id(状态)。

如果仍在发生超时,可以增加查询超时值吗? -考虑要尝试读取的大数据集。

如果这些索引没有帮助,并且期望获得良好的响应时间,那么您应该查看硬件限制-您的硬件是否足够好(请阅读mongodb的工作集大小)。如果确实需要关注性能并且您的数据量将不断增长,请扩大服务器/硬件的规模或查看分片。

OR-将状态2和3存储在单独的集合中,以减少查询时的“工作集大小”。

相关问题