時系列データについて
内部的には、 MongoDBは共通の metaField
値に基づいて時系列コレクション内のドキュメントをグループ化することで、時系列データを最適化します。有用な を選択すると、ストレージとクエリ パフォーマンスが大幅に最適化されます。詳細については、 metaField を参照してください。
時系列データのプロパティ
時系列データには、他のデータ形式と異なるプロパティがいくつかあります。
ドキュメントは順番に配置されるため、追加するには頻繁に挿入操作が必要です。
各ドキュメントはその時点を表す 1 つの点を表すため、更新操作はほとんどありません。
アプリケーションが広範な履歴レコードを保持することでメリットを得る場合、削除操作はまれに発生します。
データは、時間と、そのデータが属する一意の時系列を識別する株式ティッカーなどの識別子によってインデックス化されます。
個々の時系列ごとに必要な数のドキュメントが必要になるため、データは大量にあります。
これらの要因を考慮するために、 MongoDBでは各時系列のドキュメントをグループ化する専用の列指向形式を使用します。これには、次の利点があります。
ストレージとインデックスのサイズ縮小
クエリ効率の向上
読み取り操作の I/O を削減
WiredTigerインメモリキャッシュの使用量が増加し、クエリ速度が向上
時系列データの操作の簡素化
時系列コレクションと通常のコレクションの比較
通常のコレクションでは、データはディスクのブロックとして順番に保存され、書込み速度が最適化されます。ただし、 データ点ごとに 1 つのインデックスが必要になるため、すぐに非常に大きくなります。また、ユーザーが 1 つのシリーズに対してクエリを実行できるように、時系列識別子とタイムスタンプ自体を含む 2 番目のインデックスも必要です。このデータを読み取るには、ブロックに関連するドキュメントが 1 つしか含まれていない場合でも、 MongoDBはそのデータを含むすべてのデータベースブロックとディスク ブロックを処理する必要があります。
このモデルはCRUD操作と頻繁な更新に最適化されています。 DBアカウントの残高は現在の状態を反映しているだけで済むため、その情報が変更されるたびに各アカウント所有者のドキュメントが更新されます。
これを時系列コレクションと比較してください。時系列コレクションはデータを順番に書込まれるため、最近のトランザクションをメモリに保持するとより高速な検索が可能になります。ドキュメントは順番に書き込まれるため、ドキュメントがメモリに存在しなくなります。そのため、ドキュメントがメモリに存在しなくなります。データはmetaField
によってインデックス化されるため、インデックスははるかに小さくなります。
バケットの仕組み
時時系列コレクションを作成すると、 MongoDBは自動的にsystem.buckets
システムコレクションを作成します。 MongoDBは次の両方を持つドキュメントをグループ化します。
時系列を一意に識別する同一の
metaField
値。metaField
がオブジェクトまたは配列の場合、 MongoDBは、すべてのオブジェクトフィールドまたは配列要素が一致する場合にのみグループ化します。timeField
近い値。時系列コレクションのgranularity
、bucketMaxSpanSeconds
、およびbucketRoundingSeconds
パラメーターは、各バケットでカバーされる時間範囲を制御します。詳細については、「時系列データの詳細な設定 」を参照してください。
例、粒度がseconds
の場合、 MongoDBは同じ時間内のドキュメントをバケット化します。バケットに、 metaField
値がsensorA
で、かつtimeField
値が2024-08-01T18:23:21Z
であるドキュメントが含まれている場合、 metaField
がsensorB
である受信ドキュメントは、時間に関係なく別のバケットに入れられます。 sensorA
からの受信ドキュメントは、そのtimeField
が2024-08-01T18:00:00Z
と2024-08-01T18:59:59Z
の間である場合にのみ、同じバケットに入れられます。
2023-03-27T16:24:35Z
という時間が設定されたドキュメントが既存バケットに収まらない場合、MongoDB は最小時間が2023-03-27T16:00:00Z
で、最大時間が2023-03-27T19:59:59Z
の新しいバケットを作成します。
注意
時系列コレクションの粒度は変更できますが、 が 時間のバケットカバレッジなど、より細かい測定値から大まかな測定値への変更にのみ使用されます。これにより、コレクションのビュー定義が更新されますが、既存のバケット全体でデータが保存される方法は変更されません。
metaField はバケットにどのように影響するか
metaField
の値はグループ化されたドキュメントと完全に一致する必要があるため、時系列コレクション内のバケット数は一意のmetaField
値の数によって異なります。 metaField
値が細かい値または変更されているコレクションでは、スパースに圧縮された、有効期間の短いバケットが多数生成されます。これにより、ストレージが低下し、 クエリ効率が低下します。
例、次のドキュメントでは、特定の気象センサーからのデータを簡単にクエリできるため、 metadata
はmetaField
の適切な選択です。これらのフィールドを使用して、 MongoDBは 1 つのセンサーからの読み取りをまとめてバケット化します。
{ timestamp: ISODate("2021-05-18T00:00:00.000Z"), metadata: { sensorId: 5578, type: 'temperature' }, temp: 12, _id: ObjectId("62f11bbf1e52f124b84479ad") }
バケットカタログ
バケットカタログは、 WiredTigerの専用メモリ内キャッシュです。バケットを追跡してレイテンシを最小限に抑え、同時書込みを調整します。
カタログには、オープンバケットごとに、 metaField
、アクティブなライター、カバーする時間、ドキュメント数、サイズ、最近の操作などの情報が保持されます。 MongoDBはmetaField
が異なるドキュメント用に個別のバケットを作成するため、通常、複数のバケットは同時に開かれます。
競合状態によって発生する不整合を避けるため、競合する操作が実行されたときにバケットを閉じてバケットカタログから削除することができます。 mongod
を再起動すると、すべてのバケットが閉じられ、バケットカタログがリセットされます。
創造
MongoDBは、受信ドキュメントに適したバケットがない場合は新しいバケットを作成します。これは、次のいずれかに当てはまる場合に発生します。
ドキュメント
metaField
はアクティブなバケットに一致しません。ドキュメントタイムスタンプがすべてのアクティブ バケットの範囲外です。
ドキュメントが、すべてのアクティブ バケットの残りのサイズまたはドキュメント制限を超えています。
新しいバケットの開始タイムスタンプは、コレクションの粒度に基づいて切り捨てられます。これは、タイムスタンプが異なる順序を持つドキュメントが連続して到着するケースを処理します。
閉鎖
MongoDBは、次のいずれかの状況でバケットを閉じます。
時間が対象時間範囲を超えて過去または逆方向に移動されたことは、バケットの境界外の受信ドキュメントのタイムスタンプによって示されます。これらの限界は、コレクションの粒度設定によって決まります。
バケットはドキュメント制限に達しました(デフォルトは1000 )。
バケットがストレージサイズ制限を超えました。これは、次の場合に発生します。
サイズが許可最大値(デフォルトでは125 KinB)を超えています。
ドキュメント数が最小数(デフォルト10 )およびサイズが12 MiB 未満です。
これは、データがより少なく大きなドキュメントで構成されている場合にパフォーマンスを最適化する設定の内部制限です。
アクティブなバケットのセットが許可されたストレージエンジンキャッシュサイズ に収まらない。この情報は、
collStats
データベースコマンドを使用して確認できます。
バケットカタログが許可されているメモリ割り当ての合計(デフォルトでは 、使用可能なシステム メモリの2.5 %)を超えています
チャンクの移行やアップデートなどの 競合操作により、バケットのディスク上の状態が変更されます。
mongod
が再起動します。これにより、すべてのバケットが閉じられます。
削除
MongoDBは、次の場合にバケットを削除します。
許可される最大タイムスタンプは、現在の時刻からコレクションの
expireAfterSeconds
パラメータを引いた値より小さいです。これは、 TTL コレクションの有効期間と同じです。delete
またはdb.collection.deleteMany()
コマンドは、バケット内の最後のドキュメントを削除します。