All Products
Search
Document Center

ApsaraDB for MongoDB:Praktik terbaik untuk indeks TTL di ApsaraDB for MongoDB

Last Updated:Sep 17, 2026

Indeks TTL (Time-To-Live) adalah indeks khusus single-field yang digunakan MongoDB untuk menghapus dokumen secara otomatis setelah melewati waktu kedaluwarsa. Topik ini menjelaskan cara kerja indeks TTL, cara membuat dan mengelolanya, batasan-batasannya, masalah umum beserta solusinya, serta praktik terbaik penggunaan indeks TTL di ApsaraDB for MongoDB.

Ikhtisar

Indeks TTL (Time-To-Live) adalah indeks khusus single-field yang digunakan MongoDB untuk menghapus dokumen secara otomatis setelah mencapai waktu kedaluwarsa yang ditentukan. Indeks TTL cocok untuk mengelola data dengan siklus hidup yang jelas, seperti catatan log, informasi sesi, cache sementara, dan kode verifikasi. Dengan menggunakan indeks TTL secara tepat, Anda dapat mengontrol volume data dalam sebuah collection dan mencegah pertumbuhan penyimpanan yang tidak terkendali.

Namun, penggunaan indeks TTL yang tidak tepat di lingkungan produksi dapat menyebabkan berbagai masalah, termasuk lonjakan CPU periodik, penundaan penghapusan data yang telah kedaluwarsa, dan pertumbuhan ruang disk yang terus-menerus. Topik ini menjelaskan cara kerja indeks TTL, cara menggunakannya, masalah umum, serta praktik terbaik untuk membantu Anda menggunakan indeks TTL dengan benar di ApsaraDB for MongoDB.

Cara kerja indeks TTL

Mekanisme dasar

Saat proses mongod dimulai, MongoDB membuat thread latar belakang bernama TTLMonitor. Secara default, thread ini menjalankan satu putaran pembersihan TTL setiap 60 detik. Setiap putaran melakukan operasi berikut:

  1. Mengumpulkan semua indeks TTL di database saat ini.

  2. Membuat rencana eksekusi untuk setiap indeks TTL secara bergiliran dan melakukan pembersihan data.

  3. Menghapus dokumen-dokumen yang nilai bidang indeksnya ditambah expireAfterSeconds lebih awal dari waktu saat ini.

Ambang batas kedaluwarsa dihitung sebagai berikut: nilai tanggal pada bidang indeks ditambah jumlah detik yang ditentukan oleh expireAfterSeconds. Jika hasilnya lebih awal dari waktu saat ini, dokumen tersebut dianggap telah kedaluwarsa.

Perilaku dalam replica set

Dalam replica set, thread latar belakang TTL hanya melakukan operasi penghapusan pada node Primary. Thread TTL pada node Secondary tetap idle dan menyinkronkan operasi penghapusan dengan mereplikasi oplog dari node Primary. Artinya, penghapusan TTL menghasilkan entri oplog tambahan dan dapat memengaruhi replikasi lag pada replica set.

Perbedaan versi: optimasi penghapusan batch (MongoDB 7.0+)

Mulai MongoDB 7.0 (fitur yang awalnya diperkenalkan dalam versi pengembangan 6.1), penghapusan TTL menggunakan mekanisme "fair delete" yang mengalokasikan waktu penghapusan untuk setiap indeks TTL secara time-slice. Hal ini mencegah data kedaluwarsa dalam koleksi tertentu tidak pernah dibersihkan. Peningkatan utamanya adalah sebagai berikut:

  • ttlMonitorBatchDeletes: Mengaktifkan mode penghapusan batch. Diaktifkan secara default. Saat diaktifkan, penghapusan TTL didistribusikan lebih merata di seluruh koleksi.

  • ttlIndexDeleteTargetTimeMS: Batas waktu maksimum per putaran penghapusan untuk setiap indeks TTL. Nilai default: 1000 ms.

  • ttlIndexDeleteTargetDocs: Batas atas jumlah dokumen yang dihapus per putaran untuk setiap indeks TTL. Nilai default: 50.000.

  • ttlMonitorSubPassTargetSecs: Batas waktu maksimum untuk sub-pass yang melakukan iterasi melalui indeks TTL. Nilai default: 60 detik.

Parameter-parameter ini muncul sebagai tahap BATCHED_DELETE dalam rencana eksekusi dan dapat dilihat dengan menggunakan perintah explain.

Membuat dan mengelola indeks TTL

Membuat indeks TTL

Gunakan metode createIndex untuk membuat indeks TTL pada bidang bertipe Date.

Contoh 1: Buat indeks TTL agar dokumen kedaluwarsa 3600 detik setelah nilai bidang lastModifiedDate.

db.eventlog.createIndex(
  { "lastModifiedDate": 1 },
  { expireAfterSeconds: 3600 }
)

Contoh 2: Kedaluwarsa pada waktu tertentu. Atur expireAfterSeconds ke 0 sehingga hanya nilai bidang yang menentukan waktu kedaluwarsa.

db.sessions.createIndex(
  { "expireAt": 1 },
  { expireAfterSeconds: 0 }
)

Memodifikasi waktu kedaluwarsa indeks TTL

Gunakan perintah collMod untuk mengubah nilai expireAfterSeconds pada indeks TTL yang sudah ada tanpa perlu membangun ulang indeks.

db.runCommand({
  "collMod": "log_events",
  "index": {
    "keyPattern": { "createdAt": 1 },
    "expireAfterSeconds": 600
  }
})

Mengonversi indeks reguler menjadi indeks TTL (MongoDB 6.0+)

Mulai MongoDB 6.0, Anda dapat menggunakan perintah collMod untuk mengonversi indeks single-field reguler yang sudah ada menjadi indeks TTL, tanpa harus menghapus dan membangun ulangnya terlebih dahulu.

db.runCommand({
  "collMod": "tickets",
  "index": {
    "keyPattern": { "lastModifiedDate": 1 },
    "expireAfterSeconds": 100
  }
})

Memantau status TTL

Anda dapat memantau operasi TTL dengan menggunakan perintah-perintah berikut.

// Lihat jumlah total dokumen yang dihapus oleh TTL
db.serverStatus().metrics.ttl.deletedDocuments

// Lihat jumlah pass thread TTL
db.serverStatus().metrics.ttl.passes

// Lihat interval pemindaian TTL (default: 60 detik)
db.runCommand({ getParameter: 1, ttlMonitorSleepSecs: 1 })

// Lihat operasi penghapusan TTL yang sedang berjalan
db.currentOp()

Batasan indeks TTL

Sebelum menggunakan indeks TTL, Anda harus memahami batasan penting berikut:

  • Indeks TTL hanya mendukung indeks single-field. Indeks compound tidak dapat menggunakan fitur TTL. Bahkan jika Anda mengatur expireAfterSeconds, pengaturan tersebut akan diabaikan.

  • Bidang _id tidak mendukung indeks TTL.

  • Bidang yang diindeks harus bertipe BSON Date. Jika nilai bidang bukan bertipe Date (misalnya integer stempel waktu UNIX atau string), dokumen tidak akan dihapus secara otomatis.

  • Dokumen yang tidak mengandung bidang yang diindeks tidak akan kedaluwarsa.

  • Jika bidang berupa array, nilai tanggal paling awal dalam array digunakan untuk menghitung waktu kedaluwarsa.

  • Anda tidak dapat memodifikasi indeks TTL yang sudah ada dengan menggunakan createIndex; Anda harus menggunakan perintah collMod.

  • expireAfterSeconds harus berada dalam rentang 0 hingga 2.147.483.647, dan tidak boleh diatur ke NaN. Jika tidak, perilaku tak terduga dan kehilangan data dapat terjadi.

Masalah umum dan solusi

Masalah 1: Lonjakan CPU periodik akibat penghapusan TTL

Gejala

Penggunaan CPU instans menunjukkan puncak periodik yang jelas pada interval tetap. Dengan menjalankan db.currentOp(), Anda dapat mengamati bahwa thread TTL sedang melakukan banyak operasi penghapusan.

Penyebab

Ketika aplikasi memasukkan sejumlah besar data pada saat yang sama dan nilai bidang TTL-nya sama atau saling berdekatan, dokumen-dokumen tersebut akan kedaluwarsa dalam jendela waktu yang sama. Thread TTL perlu menghapus banyak dokumen dalam satu pemindaian, sehingga memberikan tekanan signifikan pada CPU dan I/O.

Solusi

  • Sebarkan waktu kedaluwarsa: Saat memasukkan data, tambahkan offset acak ke bidang TTL untuk menyebarkan waktu kedaluwarsa dalam rentang waktu tertentu dan menghindari penghapusan massal. Misalnya, untuk data yang kedaluwarsa dalam 24 jam, tambahkan atau kurangi offset acak beberapa menit dari waktu kedaluwarsa.

  • Tingkatkan ke MongoDB 7.0 atau versi lebih baru: Gunakan mekanisme penghapusan batch dan fair delete untuk meratakan tekanan penghapusan.

  • Pilih spesifikasi instans yang sesuai: Pastikan instans memiliki CPU dan memori yang cukup untuk menangani beban tambahan dari penghapusan TTL.

Contoh: Tambahkan offset kedaluwarsa acak pada data yang dimasukkan.

// Tambahkan offset acak 0 hingga 600 detik di atas 24 jam
var randomOffset = Math.floor(Math.random() * 600);
var expireTime = new Date(Date.now() + (86400 + randomOffset) * 1000);
db.logs.insertOne({
  data: "log content",
  createdAt: expireTime
})

Masalah 2: Data tidak dihapus setelah kedaluwarsa

Gejala

Dokumen telah melewati waktu kedaluwarsa yang diharapkan tetapi masih ada dalam koleksi.

Langkah pemecahan masalah

  1. Verifikasi tipe bidang: Periksa apakah nilai bidang yang diindeks TTL bertipe BSON Date. Kesalahan umum adalah menggunakan integer stempel waktu UNIX alih-alih objek Date.

    // Periksa tipe bidang
    db.collection.findOne({}, { createdAt: 1 })
    // Benar: ISODate("2024-01-01T00:00:00Z")
    // Salah: 1704067200 (integer timestamp)
  2. Verifikasi keberadaan bidang: Periksa apakah dokumen benar-benar mengandung bidang yang diindeks TTL. Dokumen yang tidak mengandung bidang tersebut tidak akan dihapus secara otomatis.

  3. Periksa definisi indeks: Verifikasi bahwa indeks mencakup properti expireAfterSeconds.

    db.collection.getIndexes()
  4. Periksa arah indeks: Pastikan indeks TTL dalam urutan ascending (nilainya 1). Indeks descending dapat menyebabkan TTL tidak berfungsi dengan baik. Jika arah indeks salah, hapus dan buat ulang indeks tersebut.

  5. Periksa apakah TTL Monitor diaktifkan: Verifikasi bahwa parameter ttlMonitorEnabled diatur ke true.

    db.adminCommand({ getParameter: 1, ttlMonitorEnabled: 1 })

Masalah 3: Penghapusan TTL tidak mampu mengimbangi laju pemasukan data

Gejala

Jumlah data dalam koleksi terus bertambah dan penggunaan disk terus meningkat, meskipun indeks TTL telah dikonfigurasi.

Penyebab

Thread TTL bersifat single-threaded dan berjalan setiap 60 detik. Ketika laju pemasukan data jauh melebihi laju pembersihan TTL, data yang telah kedaluwarsa menumpuk. Selain itu, jika terdapat beberapa indeks TTL pada satu instans, indeks tersebut diproses secara serial, yang semakin mengurangi efisiensi pembersihan.

Solusi

  • Atur ulang frekuensi pemindaian: Anda dapat memperpendek interval pemindaian dengan mengatur parameter ttlMonitorSleepSecs. Perhatikan bahwa frekuensi yang lebih tinggi akan meningkatkan beban sistem.

    // Atur interval pemindaian menjadi 10 detik
    db.adminCommand({ setParameter: 1, ttlMonitorSleepSecs: 10 })
  • Lakukan pembersihan di sisi aplikasi: Untuk skenario dengan volume tulis sangat tinggi, terapkan penghapusan batch terjadwal di aplikasi Anda alih-alih sepenuhnya mengandalkan indeks TTL.

  • Pertimbangkan koleksi berpartisi berdasarkan waktu: Untuk skenario tulis ekstrem, partisi data ke dalam koleksi berdasarkan waktu dan hapus seluruh koleksi yang telah kedaluwarsa. Ini jauh lebih efisien daripada menghapus dokumen satu per satu dengan indeks TTL.

Masalah 4: Ruang disk tidak dilepaskan setelah penghapusan

Gejala

TTL telah menghapus banyak dokumen, tetapi penggunaan disk tidak berkurang secara signifikan.

Solusi

MongoDB menggunakan mesin penyimpanan WiredTiger. Saat dokumen dihapus, ruang tersebut ditandai sebagai dapat digunakan kembali tetapi tidak langsung dikembalikan ke sistem operasi. Untuk segera mengembalikan ruang disk, jalankan perintah compact atau bangun ulang file data melalui initial sync. Kami menyarankan Anda menjalankan compact selama jam sepi.

Praktik terbaik

1. Pastikan tipe data yang benar

Indeks TTL hanya berfungsi pada bidang bertipe BSON Date. Kami menyarankan Anda menegakkan tipe tanggal yang benar untuk bidang TTL di sisi aplikasi atau dengan menggunakan fitur Validasi Skema MongoDB.

db.createCollection("sessions", {
  validator: {
    $jsonSchema: {
      properties: {
        expireAt: { bsonType: "date", description: "Bidang TTL harus bertipe Date" }
      },
      required: ["expireAt"]
    }
  }
})

2. Sebarkan waktu kedaluwarsa untuk menghindari penghapusan massal

Ini adalah cara paling efektif untuk mencegah lonjakan CPU akibat penghapusan TTL. Saat memasukkan data, tambahkan offset acak ke waktu kedaluwarsa sehingga sekelompok data kedaluwarsa dalam rentang waktu tertentu. Dengan demikian, thread TTL hanya menghapus sedikit dokumen per pemindaian, yang secara signifikan mengurangi dampak pada kinerja sistem.

Catatan

Untuk data dengan periode retensi panjang (seperti 24 jam atau lebih), kami menyarankan Anda menambahkan offset acak 0 hingga 10 menit ke waktu kedaluwarsa.

3. Sesuaikan expireAfterSeconds dengan hati-hati

Menurunkan nilai expireAfterSeconds pada indeks TTL yang sudah ada menyebabkan banyak dokumen yang ada langsung kedaluwarsa, yang dapat memicu operasi penghapusan skala besar dan sangat memengaruhi kinerja instans. Kami menyarankan hal berikut:

  1. Perkirakan berapa banyak dokumen yang akan langsung kedaluwarsa setelah penyesuaian.

  2. Lakukan perubahan selama jam sepi.

  3. Jika jumlah dokumen yang kedaluwarsa besar, hapus sebagian data terlebih dahulu secara batch menggunakan skrip, lalu modifikasi expireAfterSeconds.

4. Pertimbangan saat membuat indeks TTL baru

Membuat indeks TTL pada koleksi yang sudah berisi banyak dokumen yang memenuhi kondisi kedaluwarsa dapat memicu penghapusan skala besar segera setelah indeks dibuat. Kami menyarankan hal berikut:

  • Buat indeks TTL selama jam sepi.

  • Bersihkan data kedaluwarsa historis terlebih dahulu, lalu buat indeks TTL.

  • Buat indeks di latar belakang untuk menghindari gangguan pada bisnis reguler.

5. Jangan nonaktifkan TTL Monitor dalam waktu lama

Meskipun Anda dapat menonaktifkan fitur TTL sementara dengan mengatur parameter ttlMonitorEnabled, kami tidak menyarankan untuk membiarkannya dinonaktifkan dalam waktu lama di lingkungan produksi. Banyak dokumen kedaluwarsa yang menumpuk selama periode dinonaktifkan akan dihapus sekaligus saat fitur diaktifkan kembali, yang dapat menyebabkan masalah kinerja serius.

Peringatan

Setelah menonaktifkan TTL Monitor sementara, segera aktifkan kembali untuk mencegah penumpukan data kedaluwarsa.

6. Evaluasi dampak TTL terhadap oplog

Setiap dokumen yang dihapus oleh TTL menghasilkan entri oplog. Saat volume penghapusan besar, volume penulisan oplog meningkat signifikan, yang dapat memengaruhi replikasi lag pada replica set. Kami menyarankan Anda mengevaluasi dampaknya dengan cara berikut:

  • Monitor metrics.ttl.deletedDocuments untuk melacak volume penghapusan TTL.

  • Monitor replikasi lag pada replica set untuk memastikan node Secondary mampu menangani oplog tambahan yang dihasilkan oleh TTL.

  • Tingkatkan ukuran oplog jika diperlukan untuk mencegah overflow oplog akibat penghapusan TTL.

7. Alternatif untuk skenario tulis tinggi

Indeks TTL cocok untuk skenario dengan volume tulis moderat. Untuk skenario dengan volume tulis sangat tinggi, pertimbangkan alternatif berikut:

  1. Koleksi berpartisi berdasarkan waktu: Partisi koleksi berdasarkan dimensi waktu (misalnya per hari atau per minggu) dan hapus seluruh koleksi yang telah kedaluwarsa. Ini adalah cara paling efisien untuk mengedaluwarsakan data.

  2. Koleksi deret waktu: MongoDB 5.0+ mendukung koleksi deret waktu, yang mencakup kedaluwarsa data bawaan dan menghapus data secara batch berdasarkan bucket. Ini jauh lebih efisien daripada menghapus dokumen satu per satu dalam koleksi reguler.

  3. Pembersihan terjadwal di sisi aplikasi: Gunakan tugas terjadwal untuk melakukan penghapusan batch selama jam sepi, yang memberi Anda kontrol lebih tepat atas laju dan waktu penghapusan.

Fitur TTL berdasarkan versi

Versi

Fitur

6.0+

Mendukung konversi indeks single-field reguler menjadi indeks TTL menggunakan collMod, tanpa perlu menghapus dan membangun ulang indeks terlebih dahulu.

7.0+

Memperkenalkan mekanisme penghapusan batch (BATCHED_DELETE), yang meningkatkan efisiensi penghapusan; menerapkan fair delete untuk mencegah koleksi tertentu "kelaparan"; mendukung indeks TTL parsial untuk koleksi deret waktu dan partialFilterExpression yang lebih fleksibel.

Referensi parameter TTL

Parameter

Deskripsi

Nilai default

ttlMonitorSleepSecs

Interval pemindaian thread TTL.

60 detik

ttlMonitorEnabled

Sakelar untuk fitur TTL.

true

ttlMonitorBatchDeletes

Mode penghapusan batch (7.0+).

true

ttlIndexDeleteTargetTimeMS

Batas waktu maksimum per putaran penghapusan (7.0+).

1000 ms

ttlIndexDeleteTargetDocs

Batas atas jumlah dokumen yang dihapus per putaran (7.0+).

50000

ttlMonitorSubPassTargetSecs

Batas waktu maksimum untuk sub-pass (7.0+).

60 detik

Ringkasan

Indeks TTL adalah mekanisme kedaluwarsa data otomatis yang andal dan praktis di MongoDB yang secara efektif mengelola data dengan siklus hidup yang ditentukan. Di lingkungan produksi, konfigurasikan sesuai skenario bisnis Anda untuk menghindari masalah kinerja. Poin-poin utamanya adalah sebagai berikut:

  1. Pastikan bidang TTL bertipe BSON Date. Ini adalah prasyarat agar indeks TTL berfungsi dengan baik.

  2. Menyebarluaskan waktu kedaluwarsa adalah cara paling efektif untuk menghindari lonjakan CPU.

  3. Pantau terus status TTL (volume penghapusan, jumlah pass pemindaian, replikasi lag).

  4. Untuk skenario tulis tinggi, pertimbangkan alternatif seperti koleksi berpartisi berdasarkan waktu atau koleksi deret waktu.

  5. Upgrade ke versi yang lebih baru (seperti 7.0+) memberikan kinerja dan keadilan penghapusan TTL yang lebih baik.