時系列コレクションへのセカンダリインデックスの追加
時系列コレクションのクエリ パフォーマンスを向上させるには、一般的な時系列クエリ パターンをサポートするために 1 つ以上のセカンダリ インデックスを追加します。 MongoDB 6.3以降、 MongoDB は、新しいコレクションの metaField
とtimeField
フィールドに複合インデックスを自動的に作成します。
注意
すべてのインデックス タイプがサポートされているわけではありません。 サポートされていないインデックス タイプのリストについては、「時系列コレクションのセカンダリインデックスの制限 」を参照してください。
追加の セカンダリ インデックス を作成することもできます。 構成を持つ気象データコレクションを考えてみましょう。
db.createCollection( "weather", { timeseries: { timeField: "timestamp", metaField: "metadata" }})
各気象データ ドキュメントで、 metadata
フィールド値は、気象センサーの ID とタイプのフィールドを含むサブドキュメントです。
{ "timestamp": ISODate("2021-05-18T00:00:00.000Z"), "metadata": { "sensorId": 5578, "type": "temperature" }, "temp": 12 }
コレクションのデフォルトの複合インデックスはmetadata
サブドキュメント全体をインデックス化するため、このインデックスは$eq
クエリでのみ使用されます。 特定のmetadata
フィールドをインデックス化することで、他のクエリ タイプのクエリ パフォーマンスが向上します。
たとえば、次の$in
クエリにはmetadata.type
のセカンダリ インデックスがメリットとして得られます。
{ metadata.type:{ $in: ["temperature", "pressure"] }}
セカンダリインデックスを使用したソートのパフォーマンス向上
時系列コレクションのソート操作では、 timeField
フィールドでセカンダリ インデックスを使用できます。 特定の条件下、ソート操作では、 フィールドと フィールドで複合セカンダリmetaField
timeField
インデックスを使用することもできます。
集計パイプライン ステージ$match
と$sort
によって、時系列コレクションで使用できるインデックスが決まります。 インデックスは、次のシナリオで使用できます。
{ <timeField>: ±1 }
でのソートでは<timeField>
のセカンダリ インデックスを使用します{ <metaField>: ±1, timeField: ±1 }
でのソートでは、{ <metaField>: ±1, timeField: ±1 }
のデフォルトの複合インデックスが使用されます{ <timeField>: ±1 }
でのソートでは、<metaField>
に点述語がある場合、{ metaField: ±1, timeField: ±1 }
のセカンダリ インデックスが使用されます
たとえば、次の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, } } ] )
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 }
注意
最後のポイント クエリは、 Distinguished_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
であり、これはインデックスが使用されたことを示します。 説明プランの出力の詳細については、「説明結果 」を参照してください。
時系列コレクションのインデックスヒントの指定
インデックスのヒントにより、MongoDB はクエリに特定のインデックスを使用するようになります。 時系列コレクションに対する一部の操作では、ヒントでインデックスが指定されている場合にのみインデックスを利用できます。
たとえば、次のクエリでは、MongoDB はtimestamp_1_metadata.sensorId_1
インデックスを使用します。
db.sensorData.find( { "metadata.sensorId": 5578 } ).hint( "timestamp_1_metadata.sensorId_1" )
時系列コレクションでは、インデックス名またはインデックス キー パターンのいずれかを使用してヒントを指定できます。 コレクションのインデックスの名前を取得するには、 db.collection.getIndexes()
メソッドを使用します。
2dsphere インデックスの作成
バージョン6.0 以降、timeField
、metaField
、または測定フィールドに 2dsphere インデックスを作成できます。
たとえば、次の操作は、location
フィールドに 2dsphere インデックスを作成します。
例
db.sensorData.createIndex({ "metadata.location": "2dsphere" })
さらに、次の操作では、測定フィールドに 2dsphere インデックスが作成されます。
例
db.sensorData.createIndex({ "currentConditions.tempF": "2dsphere" })
注意
時系列コレクションにセカンダリインデックスがあり、機能の互換性バージョン(fCV)をダウングレードする必要がある場合は、ダウングレードした fCV と互換性のないセカンダリインデックスを最初に削除する必要があります。詳細については、setFeatureCompatibilityVersion
を参照してください。