TTL Indexes
注意
ストレージ コストを節約するためにドキュメントを削除している場合、MongoDB Atlas の Online Archive の使用がおすすめです。Atlas Online Archive は、アクセス頻度の低いデータを完全自己管理型の S3 バケットに自動的にアーカイブするコスト効果の高いデータ階層化ツールです。
TTL インデックスは、MongoDB が特定の時間経過後または指定された時刻にコレクションからドキュメントを自動的に削除するために使用できる特別な単一フィールドのインデックスです。データの有効期限設定は、機械生成のイベントデータ、ログ、セッション情報など、データベースに一定の期間だけ保持する必要がある情報に対して便利です。
MongoDB Atlas でホストされている配置向け に UI で TTL インデックスを作成および管理 できます
TTL インデックスの作成
警告
TTL インデックスを作成すると、一度に削除する対象ドキュメントの数が非常に多くなる場合があります。こうした大きなワークロードは、サーバーでパフォーマンスの問題が生じる原因になることがあります。こうした問題を回避するには、営業時間外にインデックスを作成するか、対象となるドキュメントをバッチ単位で削除してからその後に作成されるドキュメントのインデックスを作成します。
TTL インデックスを作成するには、createIndex()
を使用します。Date 型または Date 型の値を含む配列のインデックス フィールドを指定します。expireAfterSeconds
オプションを使って TTL 値を秒単位で指定します。
TTLインデックスの expireAfterSeconds
値は、0
から 2147483647
の範囲内(両端を含む)である必要があります。
たとえば、eventlog
コレクションの lastModifiedDate
フィールドで TTL 値 3600
秒を使用して TTL インデックスを作成するには、mongosh
で次の操作を使用します。
db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )
MongoDB 6.3 以降では、時系列コレクションで部分的な TTL インデックスを作成できます。これらのインデックスはコレクション timeField
をキー フィールドとして使用し、metaField
で部分的なフィルター式を必要とします。
時系列コレクションには任意のexpireAfterSeconds
フィールドが含まれています。 expireAfterSeconds
を設定しない場合、 partialFilterExpression
を含む TTL インデックスを使用して、フィルターに一致するドキュメントの有効期限を設定できます。 expireAfterSeconds
を設定する場合、部分的な TTL インデックスを使用すると、一致するドキュメントの別の短い有効期限を設定できます。 partialFilterExpression
はmetaField
でのみ作成できます。
重要
コレクションの expireAfterSeconds
値が部分的な TTL インデックスの expireAfterSeconds
より小さい場合、コレクションは短い方の時間経過後にドキュメントを削除するため、TTL インデックスは効果がありません。
1970-01-01T00:00:00.000Z
の前または 2038-01-19T03:14:07.000Z
の後に timeField
タイムスタンプがあるドキュメントが時系列コレクションに含まれる場合、TTL(time to live) 機能によってコレクションからドキュメントが削除されることはありません。
次の気象データ時系列コレクションは、24時間後にドキュメントを削除します。
db.createCollection( "weather24h", { timeseries: { timeField: "timestamp", metaField: "sensor", granularity: "hours" }, expireAfterSeconds: 86400 } )
次の TTL インデックスは、MongoDB NYC 本社の気象センサーから 24 時間後ではなく 1 時間後にドキュメントを削除します。
db.eventlog.createIndex( { "timestamp": 1 }, { partialFilterExpression: { "sensor": { $eq: "40.761873, -73.984287" } } }, { expireAfterSeconds: 3600 } )
TTL 以外の単一フィールド インデックスの TTL インデックスへの変換
MongoDB 5.1 以降では、既存の単一フィールド インデックスに expireAfterSeconds
オプションを追加できます。TTL 以外の単一フィールド インデックスを TTL インデックスに変更するには、collMod
データベースコマンドを使用します。
db.runCommand({ "collMod": <collName>, "index": { "keyPattern": <keyPattern>, "expireAfterSeconds": <number> } })
次の例では、パターン { "lastModifiedDate": 1 }
を含む TTL 以外の単一フィールド インデックスを TTL インデックスに変換しています。
db.runCommand({ "collMod": "tickets", "index": { "keyPattern": { "lastModifiedDate": 1 }, "expireAfterSeconds": 100 } })
TTL インデックスの expireAfterSeconds
値の変更
TTL インデックスの expireAfterSeconds
値を変更するには、collMod
データベースコマンドを使用します。
db.runCommand({ "collMod": <collName>, "index": { "keyPattern": <keyPattern>, "expireAfterSeconds": <number> } })
次の例では、パターン { "lastModifiedDate": 1 }
を含むインデックスの expireAfterSeconds
の値を tickets
コレクションで変更しています。
db.runCommand({ "collMod": "tickets", "index": { "keyPattern": { "lastModifiedDate": 1 }, "expireAfterSeconds": 100 } })
重要
TTL インデックスのexpireAfterSeconds
パラメータを更新する前に、次の点を考慮してください。
パラメータを変更しても、インデックスの完全な再構築は さ
expireAfterSeconds
れません 。triggerただし、expireAfterSeconds
の値を減らすと、多くのドキュメントが即座に削除の対象となる可能性があり、削除操作が増加してパフォーマンスの問題が発生する可能性があります。TTL インデックスを更新する前に、ドキュメントを小さなバッチで手動で削除することをお勧めします。 これにより、クラスターへの影響を制御することができます。
多くのドキュメントを削除すると、ストレージ ファイルが断片化され、パフォーマンスにさらに影響が生じます。 スペースを再利用し、ストレージを最適化するには、コレクションに対して圧縮コマンドを実行するか、最初の同期を実行する必要がある場合があります。
動作
データの有効期限
TTL インデックスは、インデックス フィールド値から指定された秒数が経過するとドキュメントが期限切れになります。 有効期限のしきい値は、インデックス フィールドの値に、指定された秒数を加えた値になります。
フィールドが配列で、インデックスに複数の日付値がある場合、MongoDB は配列内の最も低い日付値(最も近い日付値)を使用して有効期限のしきい値を計算します。
時系列コレクションの場合、TTL インデックスは、その中のすべてのドキュメントの有効期限が切れると、バケット データの削除も行います。これは、バケットのタイムスタンプの上限に expireAfterSeconds
値を加えた値に等しくなります。たとえば、バケットに 2023-03-27T18:29:59Z
までのデータが含まれ、expireAfterSeconds
が 300 の場合、TTL インデックスは 2023-03-27T18:34:59Z
の後にバケットを期限切れにします。
ドキュメント内のインデックス付きフィールドに 1 つ以上の日付値が含まれていない場合、ドキュメントは有効期限切れになりません。
インデックス フィールドが含まれていないドキュメントは、有効期限切れになりません。
削除操作
mongod
のバックグラウンド スレッドは、インデックスの値を読み取り、コレクションから期限切れのドキュメントを削除します。
TTL スレッドによって実行される進行中の削除操作は、 db.currentOp()
の出力に表示されます。 TTL スレッドがドキュメントを削除すると、 metrics.ttl.deletedDocuments
サーバー ステータス メトリクスが増加します。
MongoDB 6.1 以降、次の機能を使用できます。
MongoDB は効率を向上するために、複数のドキュメントの削除をバッチ処理する場合があります。
explain
コマンドの結果には、バッチ処理されたドキュメント削除のための新しいBATCHED_DELETE
ステージが含まれています。
1970-01-01T00:00:00.000Z
の前または 2038-01-19T03:14:07.000Z
の後に timeField
タイムスタンプがあるドキュメントが時系列コレクションに含まれる場合、TTL(time to live) 機能によってコレクションからドキュメントが削除されることはありません。
削除プロセス
TTL バックグラウンド削除プロセスは、各 TTL インデックスで期限切れのドキュメントをチェックします。 TTL インデックスごとに、次のいずれかの条件が満たされるまで、バックグラウンド プロセスはドキュメントを削除します。
プロセスは、現在のインデックスから50000ドキュメントを削除します。
プロセスでは、現在のインデックスからドキュメントを削除するのに 1 秒かかります。
期限切れのドキュメントはすべて、現在のインデックスから削除されます。
その後、プロセスは次のインデックスに移動します。 プロセスが各 TTL インデックスを 1 回通過すると、現在のサブパスは完了し、新しいサブパスが残りの期限切れドキュメントのチェックを開始します。 TTL モニターがすべての TTL インデックスから可能なすべての候補ドキュメントを削除すると、パスは完了します。
さらに、 プロセスは現在の削除ループを60秒ごとに停止して、1 回の大きな削除に時間がかかりすぎるのを防ぎます。 このような状況が発生すると、現在のサブパスは終了し、新しいサブパスが開始されます。
パスとサブパスはそれぞれmetrics.ttl.passes
とmetrics.ttl.subPasses
サーバー ステータス メトリクスで追跡されます。
削除操作のタイミング
MongoDB は、プライマリでインデックスの構築が完了するとすぐに、期限切れのドキュメントまたは時系列バケットの削除を開始します。インデックス構築プロセスの詳細については、「入力されたコレクションでのインデックス構築」を参照してください。
TTL インデックスは、有効期限が切れたデータがその期限直後に削除されることを保証するものではありません。ドキュメントの有効期限が切れてから MongoDB がデータベースからドキュメントを削除するまでの間にタイムラグが生じる可能性があります。
期限切れのドキュメントを削除するバックグラウンド タスクは、60 秒ごとに実行されるため、ドキュメントの有効期限が切れてからバックグラウンド タスクが実行されるまでの間に、ドキュメントがコレクションに残ることがあります。MongoDB は、インデックスの完了から 0~60 秒後にドキュメントの削除を開始します。
削除操作の間隔は mongod
インスタンスのワークロードによって異なるため、バックグラウンド タスクの実行間隔が 60 秒を超えると、有効期限切れのデータがしばらく残る可能性があります。
TTL タスクが開始する削除操作は他の削除操作と同様に、フォアグラウンドで実行されます。
レプリカセット
TTL バックグラウンド スレッドはレプリカセット ノードで、ノードがプライマリ状態にある場合にのみドキュメントを削除します。TTL バックラウンド スレッドは、ノードがセカンダリ状態にある場合はアイドルになります。セカンダリ ノードはプライマリでの削除操作をレプリケートします。
クエリのサポート
TTL インデックスは、TTL 以外のインデックスと同様にクエリをサポートします。
スタンドアロンモードでの mongod
mongod
がスタンドアロンモードで実行され、system.local.replset
コレクションにデータが含まれている場合、TTL モニターは停止します。レプリカセットのノードをレプリカセットから取り出してスタンドアロンとして実行する場合、TTL モニターは無効になります。
制限事項
TTL インデックスは単一フィールドのインデックスです。複合インデックスは TTL をサポートしておらず、
expireAfterSeconds
オプションを無視します。_id
フィールドは TTL インデックスをサポートしていません。MongoDB7.0 以降では、 時系列コレクション の に 部分的な TTL インデックス
metaField
を作成できます。MongoDB の以前のバージョンでは、時系列コレクションのtimeField
の TTL インデックスのみを作成できます。既存のインデックスの
expireAfterSeconds
の値を変更するために、createIndex()
は使用できません。 代わりに、collMod
データベースコマンドを使用します。 詳しくは、「 TTL インデックスのexpireAfterSeconds
値の変更 」を参照してください。TTL 以外の単一フィールド インデックスがフィールドにすでにある場合、同じフィールドに TTL インデックスを作成できません。キー仕様が同じで、オプションのみが異なるインデックスは作成できないためです。 TTL 以外の単一フィールド インデックスを TTL インデックスに変更するには、
collMod
データベースコマンドを使用します。