再见我有一个关于mongoDB索引的问题.

我有个请求

db.my_collection.find({ "$and": [ { "expires_at": { "$ne": ISODate("0001-01-01T00:00:00Z") } }, { "expires_at": { "$lte": ISODate("2024-03-29T16:00:00Z") } }, { "operation.updated_at": { "$lte": ISODate("2024-03-29T16:00:00Z") } }], "operation.status": 3, "is_in_some_state": true, "system_type": "type3", "some_status": 1 })

我的数据库里有上百万条记录.我创建了索引

operation.status_1_expires_at_1
// some other indexes for other requests
expires_at_1_operation.updated_at_1_operation.status_1_is_in_some_state_1_system_type_1_some_status_1

我希望第二个索引,即匹配的索引,将被用于请求,但当我 Select 100时,我看到101索引被采用.

第一个问题是,为什么会这样做?

如果我告诉mongo使用第二个(精确的)索引(带有100选项),我会得到30%的搜索速度.

我试图创建一些其他索引只是为了看看是否有什么变化,当我创建100索引时,我得到了更快的搜索. 第二个问题—为什么?精确指数不是更好吗?

总结

  1. operation.status_1_expires_at_11 second+请求
  2. expires_at_1_operation.updated_at_1_operation.status_1_is_in_some_state_1_system_type_1_some_status_1 - 100 milliseconds request
  3. system_type_170毫秒请求

做了一些聚合来显示数据的表示.

db.my_collection.aggregate([{$group:{_id:"$system_type",count:{$sum:1}}},{$sort:{count:-1}}])
{ "_id" : "type1", "count" : 637289 }
{ "_id" : "type2", "count" : 295798 }
{ "_id" : "type3", "count" : 80788 }
{ "_id" : "type4", "count" : 5 }

即使我用type1作为system_type进行搜索,我也可以看到只有100个索引被使用.为什么?

会感激你的帮助.

推荐答案

您的查询条件可以分解为以下三个简单的查询条件:

const condition1 = {
  expires_at: { $ne: ISODate('0001-01-01T00:00:00Z') },
  'operation.status': 3,
  is_in_some_state: true,
  system_type: 'type3',
  some_status: 1,
};

const condition2 = {
  expires_at: { $lte: ISODate('2024-03-29T16:00:00Z') },
  'operation.status': 3,
  is_in_some_state: true,
  system_type: 'type3',
  some_status: 1,
};

const condition3 = {
  'operation.updated_at': { $lte: ISODate('2024-03-29T16:00:00Z') },
  'operation.status': 3,
  is_in_some_state: true,
  system_type: 'type3',
  some_status: 1,
};

综合指数的顺序至关重要(The Secret Behind How Databases Use Indexes).索引expires_at_1_operation.updated_at_1_operation.status_1_is_in_some_state_1_system_type_1_some_status_1condition3的查询没有太大帮助.由于condition1中的expires_at项条件涉及不平等,该指数在这方面也没有太大帮助.这个索引比operation.status_1_expires_at_1快的原因很简单,因为所有列都存在于索引中,并且数据库不需要从磁盘读取数据进行过滤.

您应该创建一个索引,如下所示:

{
  'operation.status': 1,
  is_in_some_state: 1,
  system_type: 1,
  some_status: 1,
}

这些字段的顺序取决于数据的分布;可以过滤掉更多数据的字段应该放在第一位.如果需要,可以创建两个索引:

{
  'operation.status': 1,
  is_in_some_state: 1,
  system_type: 1,
  some_status: 1,
  expires_at: 1
}
{
  'operation.status': 1,
  is_in_some_state: 1,
  system_type: 1,
  some_status: 1,
  'operation.updated_at': 1
}

expires_atoperation.updated_at应该是最后一个.

Mongodb相关问答推荐

在MogoDB中按时间间隔分组、统计文档和获取间隔时间

MongoDB 聚合 - $project 和 $match 阶段未按预期工作

Mongo聚合的具体格式

Golang 无法在 MongoDB 中创建文档

Mongodb 按数组元素聚合组

Mongo 删除最后的文件

TypeError:Cannot read property '_id' of undefined

MongoDB C# 驱动程序 2.0 InsertManyAsync 与 BulkWriteAsync

替换 MongoDB 中数组中的嵌入文档

如何使用python将csv数据推送到mongodb

SELECT 字段 AS `anothername` 的 mongodb 等效项

如何在 MongoDb 中进行类似于嵌套 Sql Select 查询的嵌套查询

Mongo查找对象内最长数组的查询

如何使用 mongoexport 导出排序数据?

ExpressJS & Mongoose REST API struct :最佳实践?

MongoDB 中的所有列

Mongo: query by key one level deep

初创公司应该考虑哪些数据库系统?

MongoDB - Permission denied for socket: /tmp/mongodb-27017.sock

如何判断 MongoDB 中是否存在字段?