AI エージェント向け: ドキュメントインデックスは https://www.mongodb.com/ja-jp/docs/llms.txt で利用できます。すべてのページの markdown バージョンは、いずれかの URL パスに .md を追加することで利用できます。
Docs Menu

時系列コレクションのベストプラクティス

このページでは、時系列コレクションのパフォーマンスとデータ使用量を向上させるためのベストプラクティスについて説明します。

時系列コレクションのデータ圧縮を最適化するには、次のアクションを実行します。

データに空のオブジェクト、配列、または文字列が含まれている場合は、圧縮を最適化するために、ドキュメントから空のフィールドを取り除きます。

例えば、次のドキュメントについて考えてみます。

{
timestamp: ISODate("2020-01-23T00:00:00.441Z"),
coordinates: [1.0, 2.0]
},
{
timestamp: ISODate("2020-01-23T00:00:10.441Z"),
coordinates: []
},
{
timestamp: ISODate("2020-01-23T00:00:20.441Z"),
coordinates: [3.0, 5.0]
}

coordinates 値が入力されたフィールドと、配列が空の coordinates フィールドは、コンプレッサーのスキーマが変更されます。スキーマの変更により、シーケンス内の 2 番目と 3 番目のドキュメントは非圧縮のままになります。

次のドキュメントに示すように、空の値を持つフィールドを取り除いて、圧縮を最適化します。

{
timestamp: ISODate("2020-01-23T00:00:00.441Z"),
coordinates: [1.0, 2.0]
},
{
timestamp: ISODate("2020-01-23T00:00:10.441Z")
},
{
timestamp: ISODate("2020-01-23T00:00:20.441Z"),
coordinates: [3.0, 5.0]
}

数値データをアプリケーションに必要な精度に四捨五入します。数値データを四捨五入して小数点の桁数を減らすと、圧縮率が向上します。

埋め込みデータモデルがアプリケーションのニーズをサポートしている場合は、ネストされたフィールドを使用します。ネストされたフィールドの動作は、通常のコレクションと時系列コレクションで同じです。

例、次の例のような気象ドキュメントを含む時系列コレクションを考えてみましょう。

{
timestamp: ISODate("2024-06-17T10:00:00Z"),
stationId: "ALPHA123",
atmosphere: {
temperature: 21.5,
humidity: 68,
pressure: 1013.25
},
wind: {
speed: 7.2,
direction: "NW"
},
precipitation: 0.5,
visibility: 10
}

MongoDB はネストされた各フィールドを個別に列圧縮を使用するため、フィールドを最上位にフラット化するのと同じ圧縮品質を提供します。結果として得られる圧縮は、ネストされたすべての フィールド を最上位のフィールドにフラット化するために発生する圧縮と同じです。

重要

Column compression requires a consistent nested field order. However, if you use a driver to interact with your data, there may be additional ordering considerations. For example, see BSON Types for ordered representation considerations for the Go driver. Refer to driver documentation for more information.

ワークロードの濃度が高い場合は、ネストされたオブジェクトをフラット化するとパフォーマンスが向上する可能性があります。例、次のドキュメントには前のドキュメントと同じデータが含まれていますが、フラット化された形式になっています。

{
timestamp: ISODate("2024-06-17T10:00:00Z"),
stationId: "ALPHA123",
atmosphere_temperature: 21.5,
atmosphere_humidity: 68,
atmosphere_pressure: 1013.25
wind_speed: 7.2,
wind_direction: "NW"
precipitation: 0.5,
visibility: 10
}

注意

アプリケーションに最も自然なデータモデルを使用します 。MongoDB、ネストされた構造によってパフォーマンス上の重大な問題が発生する場合にのみ、ドキュメントをフラット化することをお勧めします。

時系列コレクションの挿入パフォーマンスを最適化するには、以下の操作を実行します。

複数のドキュメントを挿入する場合

  • ネットワーク上の往復を回避するには、複数の ステートメントではなく、単一のinsertMany() insertOne()ステートメントを使用します。

  • 可能であれば、同じバッチに同一の metaField 値を含むデータを挿入します。

  • orderedパラメータをfalseに設定します。

たとえば、sensor A と sensor B の 2 つの metaField 値に対応する 2 つのセンサーがある場合、1 つのセンサーからの複数の測定値を含むバッチでは、測定ごとに 1 回の挿入ではなく、1 回の挿入のコストが発生します。

次の操作では 6 つのドキュメントが挿入されますが、ドキュメントはセンサー順に並べられるため、挿入コストは 2 回(metaField 値ごとに1回)しかかかりません。パフォーマンスを向上させるために、ordered パラメータは false に設定されています。

db.temperatures.insertMany(
[
{
metaField: {
sensor: "sensorA"
},
timestamp: ISODate("2021-05-18T00:00:00.000Z"),
temperature: 10
},
{
metaField: {
sensor: "sensorA"
},
timestamp: ISODate("2021-05-19T00:00:00.000Z"),
temperature: 12
},
{
metaField: {
sensor: "sensorA"
},
timestamp: ISODate("2021-05-20T00:00:00.000Z"),
temperature: 13
},
{
metaField: {
sensor: "sensorB"
},
timestamp: ISODate("2021-05-18T00:00:00.000Z"),
temperature: 20
},
{
metaField: {
sensor: "sensorB"
},
timestamp: ISODate("2021-05-19T00:00:00.000Z"),
temperature: 25
},
{
metadField: {
sensor: "sensorB"
},
timestamp: ISODate("2021-05-20T00:00:00.000Z"),
temperature: 26
}
],
{ "ordered": false }
)

ドキュメントでコンシステントなフィールド順序を使用すると、挿入と圧縮のパフォーマンスが向上します。

注意

圧縮にはコンシステントなネストされたフィールド順序が必要です。ネストされたフィールドによる圧縮の詳細については、ネストされたフィールドのベストプラクティスを参照してください。

例、次のドキュメントを挿入すると、すべてが同じフィールド順序を持つ次のドキュメントを挿入すると、最適なパフォーマンスが得られます。

{
_id: ObjectId("6250a0ef02a1877734a9df57"),
timestamp: ISODate("2020-01-23T00:00:00.441Z"),
name: "sensor1",
range: 1
},
{
_id: ObjectId("6560a0ef02a1877734a9df66"),
timestamp: ISODate("2020-01-23T01:00:00.441Z"),
name: "sensor1",
range: 5
}

対照的に次のドキュメントは、フィールドの順序が異なるため、最適なパフォーマンスを実現しません。

{
range: 1,
_id: ObjectId("6250a0ef02a1877734a9df57"),
name: "sensor1",
timestamp: ISODate("2020-01-23T00:00:00.441Z")
},
{
_id: ObjectId("6560a0ef02a1877734a9df66"),
name: "sensor1",
timestamp: ISODate("2020-01-23T01:00:00.441Z"),
range: 5
}

コレクションにデータを書き込むクライアントの数を増やすと、パフォーマンスが向上します。

時系列コレクションのシャーディングを最適化するには、次のアクションを実行します。

metaField を使用してコレクションをシャードすると、時系列コレクションのシャードキーとして十分な濃度が得られます。

注意

MongoDB 8.0 以降、時系列コレクションで timeField をシャードキーとして使用することは非推奨です。

時系列コレクションのクエリを最適化するには、次のアクションを実行します。

metaField の選択は、アプリケーションのクエリの最適化に最も大きな影響を与えます。

  • metaField の一部として、ほとんどまたはまったく変更されないフィールドを選択します。

  • 可能であれば、metaField の一部として、フィルター式に一般的な識別子またはその他の安定値を選択します。

  • metaField の一部としてフィルタリングに使用されていないフィールドを選択することは避けてください。 代わりに、それらのフィールドを測定値として使用してください。

詳細については、「metaField の考慮事項」を参照してください。

時系列コレクションを作成すると、MongoDB は受信した時系列データをバケットにグループ化します。 粒度を正確に設定することで、データの取り込み率に基づいてデータがバケット化される頻度を制御します。

MongoDB 6.3 以降では、カスタム バケット パラメーターbucketMaxSpanSecondsとbucketRoundingSecondsを使用してバケット境界を指定し、時系列データのバケット化方法をより正確に制御できます。

同じデータソースからの受信測定値間の時間範囲に最も一致するようにgranularityまたはカスタム バケット パラメーターを設定することでパフォーマンスを向上できます。 たとえば、数百万のセンサーから気象データを記録しているものの、各センサーからのデータは 5 分に 1 回のみ記録する場合は、 granularityを"minutes"に設定するか、カスタム バケット パラメータを300 (秒)に設定できます。

この場合、 granularityをhoursに設定すると、最大 1 か月量のデータ取り込みイベントが単一のバケットにグループ化され、トラバース時間が長くなり、クエリが遅くなります。 これをsecondsに設定すると、ポーリング間隔ごとに複数のバケットが使用されます。その多くには 1 つのドキュメントのみが含まれる場合があります。

次の表は、特定のgranularity値を使用する場合に 1 バケットのデータに含まれる最大時間間隔を示しています。

granularity
granularity バケット制限

seconds

1 時間

minutes

24 時間

hours

30 日間

クエリのパフォーマンスを向上させるには、一般的なクエリ パターンをサポートするために1 つ以上のセカンダリ インデックスをtimeFieldとmetaFieldに作成します。 バージョン 6.3 以降では、MongoDB はtimeFieldとmetaFieldにセカンダリ インデックスを自動的に作成します。

  • フィルタリングと等価性のために metaField インデックスを使用する。

  • 範囲クエリには timeField やその他のインデックス付きフィールドを使用する。

  • 一般的なインデックス戦略は、時系列コレクションにも適用される。詳細については、「インデックス戦略」を参照。

MongoDB は時系列コレクションの metaField の順序を再配置します。これにより、サーバーはアプリケーションとは異なるフィールド順序でデータを保存する場合があります。metaField がオブジェクトの場合、metaField に対するクエリでは結果に一貫性がありません。これは、metaField の順序がサーバーとアプリケーションによって異なる場合があるためです。時系列 metaField でのクエリを最適化するには、metaField 全体ではなく、スカラーのサブフィールドで metaField をクエリします。

次の例では、時系列コレクションを作成しています。

db.weather.insertMany( [
{
metaField: { sensorId: 5578, type: "temperature" },
timestamp: ISODate( "2021-05-18T00:00:00.000Z" ),
temp: 12
},
{
metaField: { sensorId: 5578, type: "temperature" },
timestamp: ISODate( "2021-05-18T04:00:00.000Z" ),
temp: 11
}
] )

sensorIdとtypeのスカラー サブフィールドに対する次のクエリは、クエリ条件に一致する最初のドキュメントを返します。

db.weather.findOne( {
"metaField.sensorId": 5578,
"metaField.type": "temperature"
} )

出力例:

{
_id: ObjectId("6572371964eb5ad43054d572"),
metaField: { sensorId: 5578, type: 'temperature' },
timestamp: ISODate( "2021-05-18T00:00:00.000Z" ),
temp: 12
}

時系列コレクションは独自のデータ構造であるため、 MongoDB は個別の値に対して効率的にインデックスできません。時系列コレクションで distinct コマンドまたは db.collection.distinct() ヘルパーメソッドを使用しないでください。代わりに、次の例に示すように、$group集計を使用してドキュメントを個別の値でグループ化します。

db.foo.createIndex({"meta.project":1, "meta.type":1})
db.foo.aggregate([{$match: {"meta.project": 10}},
{$group: {_id: "$meta.type"}}])

これは、次のように機能します。

  1. meta.project と meta.type に複合インデックスを作成し、集計をサポートする。

  2. $match ステージが meta.project = 10 のドキュメントにフィルターをかける。

  3. $group ステージでは、meta.type をグループキーとして使用して、一意の値ごとに 1 つのドキュメントを出力する。

このページを評価