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

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

項目一覧

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

時系列コレクションのクエリ パフォーマンスを向上させるには、一般的な時系列クエリ パターンをサポートするために 1 つ以上のセカンダリ インデックスを追加します。 具体的には、 timeFieldおよびmetaFieldとして指定されたフィールドに 1 つ以上の複合インデックスを作成することをお勧めします。 metaFieldフィールドのフィールド値がドキュメントの場合には、そのドキュメント内のフィールドにセカンダリインデックスを作成できます。

注意

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

たとえば、次のコマンドは、 フィールドと フィールドに 複合インデックスmetadata.sensorId timestampを作成します。

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

Tip

次を参照してください。

時系列コレクションでは、インデックスを使用して、 timeFieldmetaFieldのソート パフォーマンスを向上させることができます。

たとえば、次の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.stageCOLLSCANであり、説明プランの出力には_internalBoundedSortステージが存在します。 interalBoundedSortフィールドは、クラスター化インデックスが使用されたことを示します。 explain プランの出力の詳細については、 explain の結果 を参照してください。

時系列コレクションのセカンダリインデックスを使用すると、ソート操作のパフォーマンスが向上し、インデックスを使用できるシナリオの数が増えます。

時系列コレクションのソート操作では、 timeFieldのセカンダリ インデックスを使用できます。 特定の条件下、ソート操作では、 metaFieldtimeFieldの複合セカンダリ インデックスも使用できます。

集計パイプライン ステージ$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.stageDISTINCT_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 以降では、次のことが可能になります。

注意

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

戻る

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