Docs 菜单

时间序列集合最佳实践

本页介绍了改善时间序列集合性能和数据使用情况的最佳实践。

要优化时间序列集合的插入性能,请执行以下操作。

插入多个文档时:

  • 为避免网络往返,请使用单个 insertMany() 语句,而不是多个 insertOne() 语句。

  • 如果可能,构建批次以包含每个系列的多个测量值(由元数据定义)。

  • 为了提升性能,请将 ordered 参数设置为 false

例如,如果您具有两个传感器(sensor Asensor B),则包含来自单个传感器的多个测量值的批次产生一个插入的成本,而不是每个测量值一个插入。

以下操作会插入六个文档,但仅产生两次插入的成本(每批一次),因为文档是按传感器排序的。ordered 参数设置为 false,以提升性能:

db.temperatures.insertMany( [
{
"metadata": {
"sensor": "sensorA"
},
"timestamp": ISODate("2021-05-18T00:00:00.000Z"),
temperature: 10
},
{
"metadata": {
"sensor": "sensorA"
},
"timestamp": ISODate("2021-05-19T00:00:00.000Z"),
temperature: 12
},
{
"metadata": {
"sensor": "sensorA"
},
"timestamp": ISODate("2021-05-20T00:00:00.000Z"),
temperature: 13
},
{
"metadata": {
"sensor": "sensorB"
},
"timestamp": ISODate("2021-05-18T00:00:00.000Z"),
temperature: 20
},
{
"metadata": {
"sensor": "sensorB"
},
"timestamp": ISODate("2021-05-19T00:00:00.000Z"),
temperature: 25
},
{
"metadata": {
"sensor": "sensorB"
},
"timestamp": ISODate("2021-05-20T00:00:00.000Z"),
temperature: 26
}
], {
"ordered": false
})

在文档中使用一致的字段顺序,可以提高插入性能。

例如,插入这些文档可实现最佳插入性能:

{
_id: ObjectId("6250a0ef02a1877734a9df57"),
timestamp: 2020-01-23T00:00:00.441Z,
name: 'sensor1',
range: 1
},
{
_id: ObjectId("6560a0ef02a1877734a9df66")
timestamp: 2020-01-23T01:00:00.441Z,
name: 'sensor1',
range: 5
}

相比之下,这些文档无法实现最佳的插入性能,因为其字段顺序不同:

{
range: 1,
_id: ObjectId("6250a0ef02a1877734a9df57"),
name: 'sensor1',
timestamp: 2020-01-23T00:00:00.441Z
},
{
_id: ObjectId("6560a0ef02a1877734a9df66")
name: 'sensor1',
timestamp: 2020-01-23T01:00:00.441Z,
range: 5
}

增加向集合写入数据的客户端数量可以提高性能。

要优化时间序列集合的数据压缩,请执行以下操作。

为优化压缩,如果数据包含空对象或数组,请从省略文档中的空字段。

例如,考虑以下文档:

{
time: 2020-01-23T00:00:00.441Z,
coordinates: [1.0, 2.0]
},
{
time: 2020-01-23T00:00:10.441Z,
coordinates: []
},
{
time: 2020-01-23T00:00:20.441Z,
coordinates: [3.0, 5.0]
}

具有填充值的coordinates字段与空数组之间的交替会导致压缩器的模式发生更改。模式更改会导致序列中的第二个和第三个文档保持未压缩状态。

相比之下,以下省略空数组的文档可获得最佳压缩的好处:

{
time: 2020-01-23T00:00:00.441Z,
coordinates: [1.0, 2.0]
},
{
time: 2020-01-23T00:00:10.441Z
},
{
time: 2020-01-23T00:00:20.441Z,
coordinates: [3.0, 5.0]
}

将数值数据四舍五入到应用程序所需的精度。将数值数据四舍五入到更少的小数位可提高压缩率。

为提升查询性能,请在 timeFieldmetaField创建一个或多个二级索引,以支持常见查询模式。

由于时间序列集合的独特数据结构, MongoDB 无法有效地为不同值建立索引。避免在时间序列集合中使用 distinct 命令或 db.collection.distinct()辅助方法。取而代之的是,使用 $group 聚合按不同的值对文档进行分组。

例如,要在 meta.project = 10 的文档上查询不同的 meta.type 值,而不是:

db.foo.distinct("meta.type", {"meta.project": 10})

使用:

db.foo.createIndex({"meta.project":1, "meta.type":1})
db.foo.aggregate([{$match: {"meta.project": 10}},
{$group: {_id: "$meta.type"}}])

具体操作如下:

  1. meta.projectmeta.type 上创建复合索引并支持聚合。

  2. $match 阶段过滤 meta.project = 10 的文档。

  3. $group 阶段使用meta.type作为分组键,为每个唯一值输出一个文档。