我在 MongoDB 中有一个集合,其中包含大约 200 万个文档。平均文档大小为 28KB。有几个字段,但我们关心三个字段,即“time”、“test_time”和“arr”。 “time”是一个字符串字段,以字符串格式存储日期和时间,“test_time”是一个日期字段,以日期格式存储完全相同的日期和时间。 “arr”是一个对象数组,每个对象中约有 10 个字段。 “arr”的平均长度约为 5。我们只关心名为“name”的字段之一,所以基本上是 arr.name 管道如下 - “时间”字段上的匹配阶段,其大于和小于某些特定日期 X 和 Y。之后,仅投影 {arr.name:1, _id:0}
的投影字段在另一个场景中,我运行相同的管道,但我们使用“test_time”而不是“时间”。与上面相同的投影。
Q1。在字符串字段与日期字段上搜索范围查询时,我没有看到速度发生变化。我相信 MongoDB 中的日期类型搜索会更快。你能帮我调查一下为什么会出现这种情况吗?
Q2。我有以下索引 - time_1、test_time_1、time_1_arr.name_1 和 test_time_1_arr.name_1 默认情况下,mongodb 使用 time_1 或 test_time_1 索引,而不是带有 arr.name 的复合索引。我知道这不是覆盖查询,因为在我的匹配条件中,只有时间字段上的匹配条件,而不是名称字段上的匹配条件。我不知道如何使其成为覆盖查询,以便它可以运行得更快。 目前 docsExamined = keysExamined = nReturned 这意味着它正在执行磁盘读取来检查文档。有什么方法可以优化这个吗?
要获取约 35000 个文档,需要约 6 秒的时间,考虑到我只投影 arr.name 的一个字段,并且一个文档大小约为 28KB,这似乎花费了很多时间。我还意识到默认情况下聚合管道仅分配 100MB 的 RAM,所以我如何利用我的机器的 RAM 来完全优化。
在 STRING 字段与 DATE 字段上搜索范围查询时,我没有看到速度发生变化。
MongoDB 以 BSON 格式存储数据。 根据 BSON 规范,字符串为(e_name 是以 null 结尾的字段名称):
signed_byte(2) e_name string
日期为:
signed_byte(9) e_name int64
索引将存储不带字段名的数据。 假设字符串采用 ISO8601 格式,例如“2020-07-10 15:00:00.000”,则差异将在于比较,因此使用索引的大于/小于比较将比较每个文档 24 个字节与比较每个文档 8 个字节。 但是,一旦发现差异,比较就可以提前停止,因此不太可能需要比较每个的完整字节数。
在使用索引查询的上下文中,这意味着它在索引中查找第一个匹配项,然后迭代索引直到找到不匹配的文档。 由于未涵盖查询,因此即使文档已在缓存中,获取 28KB 文档也会使比较所需的时间相形见绌。
我知道这不是一个覆盖查询,因为在我的匹配条件中,只有时间字段上的匹配条件,而不是名称字段上的匹配条件。我不知道如何使其成为覆盖查询,以便它可以运行得更快。
该查询未被覆盖,因为它无法仅通过索引来完成。
当 MongoDB 对数组进行索引时,会为每个数组元素生成一个单独的索引键。 这意味着具有 5 元素数组的文档将具有 5 个索引键,每个索引键仅包含数组元素之一。
投影
arr.name:1
意味着它应该返回一个数组,其中包含仅包含 name
字段的数组中的每个文档。 由于无法从单个索引条目直接建立,因此它会获取文档,以便可以对整个数组进行评估。
理论上,可能可以累积索引键并将具有相同 id 的键组合起来,但 MongoDB 查询执行器不会这样做。