向时间序列集合添加从节点索引
要提高 时间序列集合的查询性能,请添加一个或多个 二级索引,以支持常见的时间序列查询模式。具体来说,我们建议您在指定为 timeField
和 metaField
字段上创建一个或多个复合索引。如果 metaField
字段的字段值是文档,则可以在该文档内的字段上创建二级索引。
注意
并非所有索引类型都受支持。有关不支持的索引类型的列表,请参阅时间序列集合二级索引的限制。
例如,此命令在metadata.sensorId
和timestamp
字段上创建复合索引:
db.weather24h.createIndex( { "metadata.sensorId": 1, "timestamp": 1 } )
使用二级索引提高排序性能
time-series collection可以使用索引来提高timeField
和metaField
的排序性能。
例如,以下 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.stage
为COLLSCAN
,并且解释计划输出中存在_internalBoundedSort
阶段。 interalBoundedSort
字段表示使用了聚集索引。 有关解释计划输出的更多信息,请参阅解释结果。
时间序列集合上的二级索引可以提高排序操作的性能,并增加可以使用索引的场景数量。
对时间序列集合的排序操作可以使用timeField
上的二级索引。 在某些条件下,排序操作还可以在metaField
和timeField
上使用复合二级索引。
管道阶段$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.stage
为 DISTINCT_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 中的 time-series 二级索引
从 MongoDB 6.0 开始,您可以
在
timeField
、metaField
或测量值字段上添加复合索引。对时间序列集合上的部分索引使用
$or
、$in
和$geoWithin
操作符。在
metaField
和timeField
上添加部分索引。为任何字段或子字段添加二级索引。
使用带有2dsphere索引的
metaField
。