Docs HomeMongoDB Manual

Add Secondary Indexes to Time Series Collections向时间序列集合添加辅助索引

To improve query performance for time series collections, add one or more secondary indexes to support common time series query patterns. 要提高时间序列集合的查询性能,请添加一个或多个辅助索引以支持常见的时间序列查询模式。Starting in MongoDB 6.3, MongoDB automatically creates a compound index on the metaField and timeField fields for new collections.从MongoDB 6.3开始,MongoDB会自动在metaFieldtimeField字段上为新集合创建一个复合索引

Note

Not all index types are supported. For a list of unsupported index types, see Limitations for Secondary Indexes on Time Series Collections.并非所有索引类型都受支持。有关不受支持的索引类型的列表,请参阅时间序列集合上辅助索引的限制

You may wish to create additional secondary indexes. Consider a weather data collection with the configuration:您可能希望创建其他辅助索引。考虑使用以下配置集合天气数据:

db.createCollection(
"weather",
{
timeseries: {
timeField: "timestamp",
metaField: "metadata"
}})

In each weather data document, the metadata field value is a subdocument with fields for the weather sensor ID and type:在每个天气数据文档中,metadata字段值是一个子文档,其中包含天气传感器ID和类型的字段:

{
"timestamp": ISODate("2021-05-18T00:00:00.000Z"),
"metadata": {
"sensorId": 5578,
"type": "temperature"
},
"temp": 12
}

The default compound index for the collection indexes the entire metadata subdocument, so the index is only used with $eq queries. 集合的默认复合索引对整个metadata子文档进行索引,因此该索引仅用于$eq查询。By indexing specific metadata fields, you improve query performance for other query types.通过索引特定的metadata字段,可以提高其他查询类型的查询性能。

For example, this $in query benefits from a secondary index on metadata.type:例如,此$in查询得益于元数据类型上的辅助索引:

{ metadata.type:{ $in: ["temperature", "pressure"] }}
Tip

Use Secondary Indexes to Improve Sort Performance使用辅助索引提高排序性能

Sort operations on time series collections can use secondary indexes on the timeField field. 时间序列集合上的排序操作可以使用timeField字段上的辅助索引。Under certain conditions, sort operations can also use compound secondary indexes on the metaField and timeField fields.在某些条件下,排序操作还可以对metaFieldtimeField字段使用复合辅助索引。

The aggregation pipeline stages $match and $sort determine which indexes a time series collection can use. 聚合管道阶段$match$sort决定时间序列集合可以使用哪些索引。An index can be used in the following scenarios:索引可用于以下场景:

  • Sort on { <timeField>: ±1 } uses a secondary index on <timeField>{ <timeField>: ±1 }上排序在<timeField>上使用辅助索引
  • Sort on { <metaField>: ±1, timeField: ±1 } uses the default compound index on { <metaField>: ±1, timeField: ±1 }{ <metaField>: ±1, timeField: ±1 }上排序在{ <metaField>: ±1, timeField: ±1 }上使用默认复合索引
  • Sort on { <timeField>: ±1 } uses a secondary index on { metaField: ±1, timeField: ±1 } when there is a point predicate on <metaField>{ <timeField>: ±1 }上排序在{ metaField: ±1, timeField: ±1 }上使用辅助索引,当在<metaField>上存在点谓语时

For example, the following sensorData collection contains measurements from weather sensors:例如,以下sensorData集合包含来自天气传感器的测量值:

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

Create a secondary single-field index on the timestamp field:timestamp字段上创建辅助单字段索引:

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

The following sort operation on the timestamp field uses the Secondary Index to improve performance:以下对timestamp字段的排序操作使用辅助索引来提高性能:

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

To confirm that the sort operation used the Secondary Index, run the operation again with the .explain( "executionStats" ) option:要确认排序操作使用了辅助索引,请使用.explain( "executionStats" )选项再次运行该操作:

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

Last Point Queries on Time Series Collections时间序列集合的最后一点查询

In time series data, a last point query returns the data point with the latest timestamp for a given field. 在时间序列数据中,最后一个点查询返回具有给定字段的最新时间戳的数据点。For time series collections, a last point query fetches the latest measurement for each unique metadata value. 对于时间序列集合,最后一点查询获取每个唯一元数据值的最新测量值。For example, you may want to get the latest temperature reading from all sensors. Improve performance on last point queries by creating any of the following indexes:例如,您可能想要从所有传感器获得最新的温度读数。通过创建以下任意索引来提高最后一点查询的性能:

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

Last point queries are most performant when they use the DISTINCT_SCAN optimization. This optimization is only available when an index on timeField is descending.最后一点查询在使用DISTINCT_SCAN优化时性能最高。此优化仅在timeField上的索引递减时可用。

The following command creates a compound secondary index on metaField (ascending) and timeField (descending):以下命令在metaField(升序)和timeField(降序)上创建复合辅助索引:

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

The following last point query example uses the descending timeField compound secondary index created above:以下最后一个点查询示例使用上面创建的递减timeField复合辅助索引:

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

To confirm that the last point query used the secondary index, run the operation again using .explain( "executionStats" ):要确认最后一个点查询使用了辅助索引,请使用.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" }
}
}
] )

The winningPlan.queryPlan.inputStage.stage is DISTINCT_SCAN, which indicates that the index was used. winningPlan.queryPlan.inputStage.stageDISTINCT_SCAN,表示使用了索引。For more information on the explain plan output, see Explain Results.有关解释计划输出的更多信息,请参阅解释结果

Specify Index Hints for Time Series Collections指定时间序列集合的索引提示

Index hints cause MongoDB to use a specific index for a query. Some operations on time series collections can only take advantage of an index if that index is specified in a hint.索引提示导致MongoDB对查询使用特定的索引。只有在提示中指定了索引的情况下,时间序列集合上的某些操作才能利用该索引。

For example, the following query causes MongoDB to use the timestamp_1_metadata.sensorId_1 index:例如,以下查询导致MongoDB使用timestamp_1_metadata.sensorId_1索引:

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

On a time series collection, you can specify hints using either the index name or the index key pattern. 在时间序列集合上,可以使用索引名称或索引键模式指定提示。To get the names of the indexes on a collection, use the db.collection.getIndexes() method.要获取集合上索引的名称,请使用db.collection.getIndexes()方法。

Time Series Secondary Indexes in MongoDB 6.0 and LaterMongoDB 6.0及更高版本中的时间序列辅助索引

New in version 6.3. 6.3版新增。

Starting in MongoDB 6.3, you can create a partial TTL index for a time series collection. You can only filter on the metaField.从MongoDB 6.3开始,您可以为时间序列集合创建部分TTL索引。您只能在metaField上进行筛选。

If the collection doesn't use the expireAfterSeconds option to expire documents, creating a partial TTL index sets an expiration time for matching documents only. 如果集合不使用expireAfterSeconds选项使文档过期,则创建部分TTL索引将仅为匹配的文档设置过期时间。If the collection uses expireAfterSeconds for all documents, a partial TTL index lets you expire matching documents sooner.如果集合对所有文档使用expireAfterSeconds,则部分TTL索引可以使匹配的文档提前过期。

New in version 6.0. 6.0版新增。

Starting in MongoDB 6.0, you can:从MongoDB 6.0开始,您可以:

Note

If there are secondary indexes on time series collections and you need to downgrade the feature compatibility version (FCV), you must first drop any secondary indexes that are incompatible with the downgraded FCV. 如果时间序列集合上有辅助索引,并且需要降级功能兼容性版本(FCV),则必须首先删除与降级的FCV不兼容的所有辅助索引。See setFeatureCompatibilityVersion.请参阅setFeatureCompatibilityVersion