带有日期字段的范围查询的查询性能

Query performance of a range query with date field

我正在寻找查询的性能优化。我的目标是找到给定日期范围内的所有文档。该集合非常大,它有超过 600 万份文件。所以查询如下:

db.collection.find({
    createdAt: {
        $gte: new Date('2018-06-19'), 
        $lt: new Date('2018-06-22')
    }
})

它运行了 10 多分钟。有没有办法利用日期排序的事实?我的意思是文档是在创建时插入的,因此落入该范围的最后一个文档之后的每个文档都将超出范围,但 mongo 可能不知道这一点并寻找那些日期已经超出范围的文档??

MongoDB不能利用"the fact",因为它不知道存储的是什么二进制文件。

如果您按非索引字段搜索,Mongodb 执行 COLLSCAN(已解释 here

索引:

自 v4.2 起,MongoDB 使用优化的构建过程,仅在构建过程的开始和结束时持有独占锁。

v4.2之前需要指定background选项

db.collection.createIndex({createdAt:1}, {background:true})

https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#options-for-all-index-types

应用程序及其用户正在寻找的是对包含数百万文档的集合的查询性能在几百毫秒(而不是 10 分钟)内。索引用于使这些查询 运行 快速。

通过在查找查询过滤器的日期字段上创建单个字段索引,可以运行 快速进行上述范围查询。索引存储索引键字段值和集合中文档的地址——这是少量数据。对于典型的集合、查询和索引,集合的数据和索引需要在内存(称为工作集)中可用(或适合)才能有效使用。当查询为运行时,根据过滤条件访问索引,然后访问对应的文档。

如果不使用索引,就无法使查询 运行 更快,因为有数百万个文档(请注意,如果有几千个文档,这可能无关紧要)。这可以在 dev 环境中进行实际演示,该环境具有几百万个文档的样本集、查询过滤器字段上的索引和测试 运行.

用于执行此测试的工具正在生成一个 query plan using the explain. The explain method 具有 "executionStats" 模式,它提供了详细信息,例如使用的索引(如果有),运行 的时间查询、访问的索引键、返回的文档数、查询执行的各个阶段等。计划阶段将说明查询是否使用了索引。通常,使用索引的查询 运行 将显示索引扫描 (IXSCAN),如果未使用索引,则将显示集合扫描 (COLLSCAN)。

创建的索引还可以用于其他查询(如果适用)以及排序操作。另外,索引可以是复合索引(使用多个字段),如果它可以与其他查询一起使用。

此外,请参阅 FAQ: Indexes for more information. Since you already have a large collection see Index Builds on Populated Collections 以了解有关的注意事项。

db.collection.stats() 命令可用于查找集合的大小和索引。

除了索引之外,仅投影必填字段也会影响您的查询性能。