時系列コレクションへのセカンダリインデックスの追加
項目一覧
時系列コレクションのクエリ パフォーマンスを向上させるには、一般的な時系列クエリ パターンをサポートするために 1 つ以上のセカンダリ インデックスを追加します。 具体的には、 timeField
およびmetaField
として指定されたフィールドに 1 つ以上の複合インデックスを作成することをお勧めします。 metaField
フィールドのフィールド値がドキュメントの場合には、そのドキュメント内のフィールドにセカンダリインデックスを作成できます。
注意
すべてのインデックス タイプがサポートされているわけではありません。 サポートされていないインデックス タイプのリストについては、「時系列コレクションのセカンダリインデックスの制限 」を参照してください。
たとえば、次のコマンドは、 フィールドと フィールドに 複合インデックスmetadata.sensorId
timestamp
を作成します。
db.weather24h.createIndex( { "metadata.sensorId": 1, "timestamp": 1 } )
セカンダリインデックスを使用したソートのパフォーマンス向上
時系列コレクションでは、インデックスを使用して、 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
フィールドは、クラスター化インデックスが使用されたことを示します。 explain プランの出力の詳細については、 explain の結果 を参照してください。
時系列コレクションのセカンダリインデックスを使用すると、ソート操作のパフォーマンスが向上し、インデックスを使用できるシナリオの数が増えます。
時系列コレクションのソート操作では、 timeField
のセカンダリ インデックスを使用できます。 特定の条件下、ソート操作では、 metaField
とtimeField
の複合セカンダリ インデックスも使用できます。
集計パイプライン ステージ$match
と$sort
によって、時系列コレクションで使用できるインデックスが決まります。 次のリストでは、インデックスを使用できるシナリオについて説明しています。
{ <timeField:> ±1 }
でのソートではクラスター化インデックスが使用されます{ <timeField>: ±1 }
でのソートでは<timeField>
のセカンダリ インデックスを使用します{ <metaField>: ±1, timeField: ±1 }
でのソートでは{ <metaField>: ±1, timeField: ±1 }
のセカンダリ インデックスを使用します{ <timeField>: ±1 }
でのソートでは、<metaField>
に点述語がある場合、{ 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 }
注意
最後のポイント クエリは、 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()
メソッドを使用します。
MongoDB 6.0 の時系列セカンダリインデックス
MongoDB 6.0 以降では、次のことが可能になります。
timeField
、metaField
、または測定フィールドに複合インデックスを追加します。時系列コレクションの 部分インデックス を持つ
$or
$geoWithin
、$in
、および 演算子を使用します。metaField
とtimeField
に部分インデックスを追加します。任意のフィールドまたはサブフィールドにセカンダリ インデックスを追加します。
2dsphereインデックスで
metaField
を使用します。
注意
時系列コレクションにセカンダリインデックスがあり、機能の互換性バージョン (fCV) をダウングレードする必要がある場合は、ダウングレードした fCV と互換性のないセカンダリインデックスを最初に削除する必要があります。setFeatureCompatibilityVersion
を参照してください。