Docs 菜单
Docs 主页
/
MongoDB Manual
/

向时间序列集合添加从节点索引

在此页面上

  • 使用二级索引提高排序性能
  • 对时间序列集合的“最后一点”查询
  • 为时间序列集合指定索引提示
  • MongoDB 6.0 中的 time-series 二级索引

要提高 时间序列集合的查询性能,请添加一个或多个 二级索引,以支持常见的时间序列查询模式。具体来说,我们建议您在指定为 timeFieldmetaField 字段上创建一个或多个复合索引。如果 metaField 字段的字段值是文档,则可以在该文档内的字段上创建二级索引。

注意

并非所有索引类型都受支持。有关不支持的索引类型的列表,请参阅时间序列集合二级索引的限制

例如,此命令在metadata.sensorIdtimestamp字段上创建复合索引

db.weather24h.createIndex( { "metadata.sensorId": 1, "timestamp": 1 } )

提示

请参阅:

time-series collection可以使用索引来提高timeFieldmetaField的排序性能。

例如,以下 sensorData 集合包含来自天气传感器的测量值:

db.sensorData.insertMany( [ {
"metadata": {
"sensorId": 5578,
"location": {
type: "Point",
coordinates: [-77.40711, 39.03335]
}
},
"timestamp": ISODate("2022-01-15T00:00:00.000Z"),
"currentConditions": {
"windDirecton": 127.0,
"tempF": 71.0,
"windSpeed": 2.0,
"cloudCover": null,
"precip": 0.1,
"humidity": 94.0,
}
},
{
"metadata": {
"sensorId": 5578,
"location": {
type: "Point",
coordinates: [-77.40711, 39.03335]
}
},
"timestamp": ISODate("2022-01-15T00:01:00.000Z"),
"currentConditions": {
"windDirecton": 128.0,
"tempF": 69.8,
"windSpeed": 2.2,
"cloudCover": null,
"precip": 0.1,
"humidity": 94.3,
}
},
{
"metadata": {
"sensorId": 5579,
"location": {
type: "Point",
coordinates: [-80.19773, 25.77481]
}
},
"timestamp": ISODate("2022-01-15T00:01:00.000Z"),
"currentConditions": {
"windDirecton": 115.0,
"tempF": 88.0,
"windSpeed": 1.0,
"cloudCover": null,
"precip": 0.0,
"humidity": 99.0,
}
}
]
)

时间序列集合会自动创建内部集群索引。 查询规划器使用此索引来提高排序性能。

注意

如果在1970-01-01T00:00:00.000Z之前或2038-01-19T03:14:07.000Z之后将文档插入到具有timeField值的集合中,MongoDB 会记录警告并阻止某些查询优化使用内部索引。 timeField创建二级索引,以恢复查询性能并解决日志警告问题。

以下对timestamp字段的排序操作使用聚集索引来提高性能:

db.sensorData.find().sort( { "timestamp": 1 } )

要确认排序操作使用了集群索引,请使用.explain( "executionStats" )选项再次运行该操作:

db.sensorData.find().sort( { "timestamp": 1 } ).explain( "executionStats" )

winningPlan.queryPlan.inputStage.stageCOLLSCAN ,并且解释计划输出中存在_internalBoundedSort阶段。 interalBoundedSort字段表示使用了聚集索引。 有关解释计划输出的更多信息,请参阅解释结果。

时间序列集合上的二级索引可以提高排序操作的性能,并增加可以使用索引的场景数量。

对时间序列集合的排序操作可以使用timeField上的二级索引。 在某些条件下,排序操作还可以在metaFieldtimeField上使用复合二级索引。

管道阶段$match$sort确定time-series集合可以使用哪些索引。以下列表描述了可以使用索引的场景:

  • { <timeField:> ±1 }上的排序使用聚集索引

  • { <timeField>: ±1 } 上的排序使用 <timeField> 上的二级索引

  • { <metaField>: ±1, timeField: ±1 } 上的排序使用 { <metaField>: ±1, timeField: ±1 } 上的二级索引

  • <metaField> 上具有点谓词时,{ <timeField>: ±1 } 上的排序使用 { metaField: ±1, timeField: ±1 } 上的二级索引

timestamp字段上创建二级索引:

db.sensorData.createIndex( { "timestamp": 1 } )

以下对 timestamp 字段的排序操作使用二级索引来提高性能:

db.sensorData.aggregate( [
{ $match: { "timestamp" : { $gte: ISODate("2022-01-15T00:00:00.000Z") } } },
{ $sort: { "timestamp": 1 } }
] )

要确认排序操作使用了二级索引,请使用 .explain( "executionStats" ) 选项再次运行该操作:

db.sensorData.explain( "executionStats" ).aggregate( [
{ $match: { "timestamp": { $gte: ISODate("2022-01-15T00:00:00.000Z") } } },
{ $sort: { "timestamp": 1 } }
] )

“最后一点”查询获取每个唯一元数据值的最新测量值。 例如,您可能想获取所有传感器的最新温度读数。 通过创建以下任一索引来提高最新数据点查询的性能:

{ "metadata.sensorId": 1, "timestamp": 1 }
{ "metadata.sensorId": 1, "timestamp": -1 }
{ "metadata.sensorId": -1, "timestamp": 1 }
{ "metadata.sensorId": -1, "timestamp": -1 }

注意

最新数据点查询在使用 DISTINCT_SCAN 优化 时可实现最高性能。仅当 timeField 上的索引为降序时,才可以使用此优化。

以下命令创建一个复合二级索引,metaField 上的索引为升序,timeField 上的索引为降序:

db.sensorData.createIndex( { "metadata.sensorId": 1, "timestamp": -1 } )

以下最新数据点查询示例使用了上文中创建的降序 timeField 复合二级索引:

db.sensorData.aggregate( [
{
$sort: { "metadata.sensorId": 1, "timestamp": -1 }
},
{
$group: {
_id: "$metadata.sensorId",
ts: { $first: "$timestamp" },
temperatureF: { $first: "$currentConditions.tempF" }
}
}
] )

要确认最新数据点查询是否使用了二级索引,请使用 .explain( "executionStats" ) 再次运行该操作:

db.getCollection( 'sensorData' ).explain( "executionStats" ).aggregate( [
{
$sort: { "metadata.sensorId": 1, "timestamp": -1 }
},
{
$group: {
_id: "$metadata.sensorId",
ts: { $first: "$timestamp" },
temperatureF: { $first: "$currentConditions.tempF" }
}
}
] )

winningPlan.queryPlan.inputStage.stageDISTINCT_SCAN,表示使用了该索引。有关 Explain Plan 输出的更多信息,请参阅 Explain 结果

索引提示导致 MongoDB 使用特定的索引进行查询。如果在提示中指定了一个索引,对时间序列集合的某些操作只能利用该索引。

例如,以下查询会促使 MongoDB 使用 timestamp_1_metadata.sensorId_1 索引:

db.sensorData.find( { "metadata.sensorId": 5578 } ).hint( "timestamp_1_metadata.sensorId_1" )

在时间序列集合上,您可以使用索引名称或索引键模式指定提示。要获取集合上的索引名称,请使用 db.collection.getIndexes() 方法。

从 MongoDB 6.0 开始,您可以

后退

设置时间序列数据的粒度