Para mejorar el rendimiento de las consultas colecciones de series de tiempo, agrega uno o más índices secundarios para admitir patrones de query comunes de series temporales. A partir de MongoDB 6.3, MongoDB crea automáticamente un índice compuesto en el metaField y campos timeField para nuevas colecciones.
Nota
No todos los tipos de índices son compatibles. Para obtener una lista de tipos de índices no admitidos, consulte Limitaciones para índices secundarios en colecciones de series de tiempo.
Puede que desees crear índices secundarios adicionales. Considere una colección de datos meteorológicos con la configuración:
db.createCollection( "weather", { timeseries: { timeField: "timestamp", metaField: "metadata" }})
En cada documento de datos meteorológicos, el valor del campo metadata es un subdocumento con campos para la ID y el tipo del sensor meteorológico:
{ "timestamp": ISODate("2021-05-18T00:00:00.000Z"), "metadata": { "sensorId": 5578, "type": "temperature" }, "temp": 12 }
El índice compuesto predeterminado de la colección indexa todo el metadata subdocumento, por lo que solo se utiliza con consultas. Al $eq indexar metadata campos específicos, se mejora el rendimiento de las consultas de otros tipos.
Por ejemplo, esta $in query se beneficia de un índice secundario en metadata.type:
{ metadata.type:{ $in: ["temperature", "pressure"] }}
Utiliza índices secundarios para mejorar el rendimiento de clasificación
Las operaciones de ordenación en colecciones de series temporales pueden utilizar índices secundarios en el campo timeField. Bajo ciertas condiciones, las operaciones de ordenación también pueden utilizar índices secundarios compuestos en los campos metaField y timeField.
Las etapas del pipeline de agregación $match y $sort determinan qué índices puede utilizar una colección de series de tiempo. Un índice puede usarse en los siguientes escenarios:
El ordenamiento en
{ <timeField>: ±1 }utiliza un índice secundario en<timeField>La ordenación en
{ <metaField>: ±1, timeField: ±1 }utiliza el índice compuesto por defecto en{ <metaField>: ±1, timeField: ±1 }La ordenación en
{ <timeField>: ±1 }utiliza un índice secundario en{ metaField: ±1, timeField: ±1 }cuando existe un predicado puntual en<metaField>
Por ejemplo, la siguiente colección sensorData contiene mediciones de sensores meteorológicos:
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, } } ] )
Cree un índice secundario de campo único en el campo timestamp:
db.sensorData.createIndex( { "timestamp": 1 } )
La siguiente operación de clasificación en el campo timestamp utiliza el índice secundario para mejorar el rendimiento:
db.sensorData.aggregate( [ { $match: { "timestamp" : { $gte: ISODate("2022-01-15T00:00:00.000Z") } } }, { $sort: { "timestamp": 1 } } ] )
Para confirmar que la operación de ordenación utilizó el índice Secundario, ejecute la operación nuevamente con la opción .explain( "executionStats" ):
db.sensorData.explain( "executionStats" ).aggregate( [ { $match: { "timestamp": { $gte: ISODate("2022-01-15T00:00:00.000Z") } } }, { $sort: { "timestamp": 1 } } ] )
Consultas de último punto sobre colecciones de series temporales
En datos de series de tiempo, una query de último punto retorna el punto de datos con la timestamp más reciente para un campo dado. Para colecciones de series de tiempo, una query de último punto obtiene la medición más reciente para cada valor único de metadatos. Por ejemplo, puede que desees obtener la última medición de temperatura de todos los sensores. Mejore el rendimiento de las queries al último punto creando cualquiera de los siguientes índices:
{ "metadata.sensorId": 1, "timestamp": 1 } { "metadata.sensorId": 1, "timestamp": -1 } { "metadata.sensorId": -1, "timestamp": 1 } { "metadata.sensorId": -1, "timestamp": -1 }
Nota
Las consultas de último punto son más eficientes cuando utilizan la optimización DISTINCT_SCAN. Esta optimización solo está disponible cuando existe un índice descendente en timeField.
El siguiente comando crea un índice secundario compuesto en metaField (ascendente) y timeField (descendente):
db.sensorData.createIndex( { "metadata.sensorId": 1, "timestamp": -1 } )
El siguiente ejemplo de query de último punto utiliza el índice secundario compuesto descendente timeField creado anteriormente:
db.sensorData.aggregate( [ { $sort: { "metadata.sensorId": 1, "timestamp": -1 } }, { $group: { _id: "$metadata.sensorId", ts: { $first: "$timestamp" }, temperatureF: { $first: "$currentConditions.tempF" } } } ] )
Para confirmar que la última consulta de punto utilizó el índice secundario, ejecute la operación nuevamente usando .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" } } } ] )
El winningPlan.queryPlan.inputStage.stage es DISTINCT_SCAN, lo que indica que se utilizó el índice. Para obtener más información sobre la salida del plan de explicación, consulta Explicar resultados.
Especificar sugerencias de índice para colecciones de series de tiempo
Las sugerencias de índice hacen que MongoDB utilice un índice específico para una query. Algunas operaciones en colecciones de series temporales sólo pueden aprovechar un índice si ese índice se especifica en una indicación.
Por ejemplo, la siguiente consulta hace que MongoDB utilice el índice timestamp_1_metadata.sensorId_1:
db.sensorData.find( { "metadata.sensorId": 5578 } ).hint( "timestamp_1_metadata.sensorId_1" )
En una colección de series de tiempo, puedes especificar sugerencias usando el nombre del índice o el patrón de clave del índice. Para obtener los nombres de los índices en una colección, utiliza el método db.collection.getIndexes().
Crear índices de tipo 2dsphere
A partir de la versión 6.0 puede crear índices 2dsphere en los campos timeField, metaField, o de medición.
Por ejemplo, la siguiente operación crea un índice 2dsphere en el campo location:
Ejemplo
db.sensorData.createIndex({ "metadata.location": "2dsphere" })
Además, la siguiente operación crea un índice 2dsphere en campos de medición:
Ejemplo
db.sensorData.createIndex({ "currentConditions.tempF": "2dsphere" })
Nota
Si hay índices secundarios en colecciones de series de tiempo y necesitas degradar la versión de compatibilidad de funciones (FCV), primero debes descartar cualquier índice secundario que sea incompatible con la FCV degradada. Para obtener más información, consulta setFeatureCompatibilityVersion.