Docs Menu
Docs Home
/
MongoDBマニュアル
/

時系列コレクションへのセカンダリインデックスの追加

項目一覧

  • セカンダリインデックスを使用したソートのパフォーマンス向上
  • 時系列コレクションに対する最後のポイントクエリ
  • 時系列コレクションのインデックスヒントの指定
  • MongoDB 6.0 以降の時系列セカンダリインデックス

時系列コレクションのクエリ パフォーマンスを向上させるには、一般的な時系列クエリ パターンをサポートするために 1 つ以上のセカンダリ インデックスを追加します。 MongoDB 6.3以降、 MongoDB は、新しいコレクションの metaFieldtimeFieldフィールドに複合インデックスを自動的に作成します。

注意

すべてのインデックス タイプがサポートされているわけではありません。 サポートされていないインデックス タイプのリストについては、「時系列コレクションのセカンダリインデックスの制限 」を参照してください。

追加の セカンダリ インデックス を作成することもできます。 構成を持つ気象データコレクションを考えてみましょう。

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"] }}

Tip

次を参照してください。

時系列コレクションのソート操作では、 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.stageDISTINCT_SCANであり、これはインデックスが使用されたことを示します。 説明プランの出力の詳細については、「説明結果 」を参照してください。

インデックスのヒントにより、MongoDB はクエリに特定のインデックスを使用するようになります。 時系列コレクションに対する一部の操作では、ヒントでインデックスが指定されている場合にのみインデックスを利用できます。

たとえば、次のクエリでは、MongoDB はtimestamp_1_metadata.sensorId_1インデックスを使用します。

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

時系列コレクションでは、インデックス名またはインデックス キー パターンのいずれかを使用してヒントを指定できます。 コレクションのインデックスの名前を取得するには、 db.collection.getIndexes()メソッドを使用します。

バージョン 6.3 で追加

MongoDB 6.3 以降では、時系列コレクションの部分的なTTL インデックスを作成できます。 フィルタリングできるのはmetaFieldのみです。

コレクションでドキュメントの期限切れにexpireAfterSecondsオプションが使用されない場合、部分的な TTL インデックスを作成すると、一致するドキュメントのみの有効期限が設定されます。 コレクションがすべてのドキュメントにexpireAfterSecondsを使用している場合は、部分的な TTL インデックスを使用すると一致するドキュメントをより早く期限切れにできます。

バージョン 6.0 で追加。

MongoDB 6.0 以降では、次のことが可能になります。

注意

時系列コレクションセカンダリインデックスがあり、機能の互換性バージョン (fCV) をダウングレードする必要がある場合は、ダウングレードした fCV と互換性のないセカンダリインデックスを最初に削除する必要があります。setFeatureCompatibilityVersion を参照してください。

戻る

時系列データの粒度の設定