Mengelola pengindeksan di Azure Cosmos DB untuk MongoDB

Important

Apakah Anda ingin memigrasikan aplikasi MongoDB yang sudah ada atau menggunakan fitur MongoDB Query Language (MQL)? Pertimbangkan Azure DocumentDB.

Apakah Anda mencari solusi database untuk skenario skala tinggi dengan perjanjian tingkat layanan ketersediaan (SLA) 99,999%, skala otomatis instan, dan failover otomatis di beberapa wilayah? Pertimbangkan Azure Cosmos DB untuk NoSQL.

Azure Cosmos DB for MongoDB memungkinkan Anda menggunakan pengindeksan untuk mempercepat performa kueri. Artikel ini menunjukkan kepada Anda cara mengelola dan mengoptimalkan indeks untuk pengambilan data yang lebih cepat dan efisiensi yang lebih baik.

Pengindeksan untuk server MongoDB versi 3.6 dan yang lebih tinggi

Azure Cosmos DB untuk server MongoDB versi 3.6+ secara otomatis mengindeks _id bidang dan kunci pembagi (hanya dalam koleksi yang dibagi). API menjamin keunikan kolom _id per kunci shard.

API untuk MongoDB bekerja secara berbeda dari Azure Cosmos DB untuk NoSQL, yang mengindeks semua bidang secara default.

Memperbarui kebijakan pengindeksan

Edit kebijakan pengindeksan Anda di Data Explorer di portal Microsoft Azure. Tambahkan kolom tunggal dan indeks wildcard dari editor kebijakan pengindeksan di Pengelola Data:

Cuplikan layar editor kebijakan pengindeksan di Azure Cosmos DB untuk MongoDB.

Nota

Anda tidak dapat membuat indeks campuran menggunakan editor kebijakan pengindeksan di Data Explorer.

Jenis indeks

Bidang tunggal

Buat indeks pada bidang tunggal apa pun. Urutan pengurutan indeks bidang tunggal tidak masalah. Gunakan perintah berikut untuk membuat indeks di bidang name:

db.coll.createIndex({name:1})

Buat indeks bidang tunggal yang sama di name portal Microsoft Azure:

Cuplikan layar menambahkan indeks nama di editor kebijakan pengindeksan.

Kueri menggunakan beberapa indeks bidang tunggal jika tersedia. Buat hingga 500 indeks bidang tunggal per koleksi.

Indeks campuran (server MongoDB versi 3.6+)

Di API untuk MongoDB, gunakan indeks majemuk dengan kueri yang mengurutkan beberapa bidang sekaligus. Untuk kueri dengan beberapa filter yang tidak perlu diurutkan, buat beberapa indeks bidang tunggal sebagai ganti indeks gabungan untuk menghemat biaya pengindeksan.

Indeks gabungan atau indeks bidang tunggal untuk setiap bidang dalam indeks gabungan menghasilkan performa yang sama untuk pemfilteran dalam kueri.

Indeks majemuk pada bidang berlapis tidak didukung secara default karena keterbatasan dengan array. Jika bidang berlapis tidak memiliki array, indeks berfungsi sebagaimana mestinya. Jika bidang berlapis memiliki array pada jalur mana pun, nilai tersebut diabaikan dalam indeks.

Misalnya, indeks gabungan yang berisi people.dylan.age berfungsi dalam kasus ini karena tidak ada array pada jalurnya.

{
  "people": {
    "dylan": {
      "name": "Dylan",
      "age": "25"
    },
    "reed": {
      "name": "Reed",
      "age": "30"
    }
  }
}

Indeks gabungan yang sama tidak berfungsi dalam kasus ini karena ada array di jalur:

{
  "people": [
    {
      "name": "Dylan",
      "age": "25"
    },
    {
      "name": "Reed",
      "age": "30"
    }
  ]
}

Aktifkan fitur ini untuk akun database Anda dengan mengaktifkan kemampuan 'EnableUniqueCompoundNestedDocs'.

Nota

Anda tidak dapat membuat indeks gabungan pada array.

Perintah berikut membuat indeks campuran pada bidang name dan age:

db.coll.createIndex({name:1,age:1})

Anda dapat menggunakan indeks campuran untuk mengurutkan secara efisien pada beberapa bidang sekaligus, seperti yang diperlihatkan dalam contoh berikut:

db.coll.find().sort({name:1,age:1})

Anda juga dapat menggunakan indeks campuran sebelumnya untuk mengurutkan kueri secara efisien dengan susunan urutan yang berlawanan pada semua bidang. Berikut adalah sebuah contoh:

db.coll.find().sort({name:-1,age:-1})

Namun, urutan jalur dalam indeks campuran harus sama persis dengan kueri. Berikut adalah contoh kueri yang akan memerlukan indeks gabungan tambahan:

db.coll.find().sort({age:1,name:1})

Index Multikunci

Azure Cosmos DB membuat indeks multikunci untuk mengindeks konten dalam array. Jika Anda mengindeks bidang dengan nilai array, Azure Cosmos DB secara otomatis mengindeks setiap elemen dalam array.

Indeks geospasial

Banyak operator geospasial mendapat manfaat dari indeks geospasial. Azure Cosmos DB untuk MongoDB mendukung 2dsphere indeks. API belum mendukung 2d indeks.

Berikut ini contoh pembuatan indeks geospasial di location bidang:

db.coll.createIndex({ location : "2dsphere" })

Indeks teks

Azure Cosmos DB untuk MongoDB tidak mendukung indeks teks. Untuk kueri pencarian teks pada string, gunakan integrasi Pencarian Azure AI dengan Azure Cosmos DB.

Indeks pengganti

Gunakan indeks wildcard untuk mendukung kueri terhadap field yang tidak diketahui. Bayangkan koleksi yang memiliki data tentang keluarga.

Berikut adalah bagian dari contoh dokumen dalam koleksi tersebut:

"children": [
  {
    "firstName": "Henriette Thaulow",
    "grade": "5"
  }
]

Berikut adalah contoh lain dengan sekumpulan properti yang berbeda di children:

"children": [
  {
    "familyName": "Merriam",
    "givenName": "Jesse",
    "pets": [
      { "givenName": "Goofy" },
      { "givenName": "Shadow" }
    ]
  },
  {
    "familyName": "Merriam",
    "givenName": "John",
  }
]

Dokumen dalam koleksi ini bisa memiliki banyak properti yang berbeda. Untuk mengindeks semua data dalam children array, buat indeks terpisah untuk setiap properti atau buat satu indeks kartubebas untuk seluruh children array.

Membuat indeks karakter pengganti

Gunakan perintah berikut untuk membuat indeks wildcard pada properti apa pun dalam children:

db.coll.createIndex({"children.$**" : 1})
  • Tidak seperti di MongoDB, indeks wildcard dapat mendukung beberapa kolom dalam predikat kueri. Tidak ada perbedaan performa kueri jika Anda menggunakan satu indeks wildcard dibandingkan membuat indeks terpisah untuk setiap properti.

Buat jenis indeks berikut memakai sintaks wildcard:

  • Bidang tunggal
  • Geospatial

Mengindeks semua properti

Buat indeks wildcard pada semua kolom dengan perintah berikut:

db.coll.createIndex( { "$**" : 1 } )

Buat indeks wildcard menggunakan Data Explorer di portal Azure:

Tambahkan indeks wildcard di editor kebijakan pengindeksan

Nota

Jika Anda baru memulai pengembangan, mulailah dengan indeks wildcard pada semua bidang. Pendekatan ini menyederhanakan pengembangan dan memudahkan untuk mengoptimalkan kueri.

Dokumen dengan banyak bidang dapat memiliki biaya Unit Permintaan (RU) yang tinggi untuk penulisan dan pembaruan. Jika Anda memiliki beban kerja dengan banyak penulisan, gunakan jalur yang diindeks secara individual alih-alih wildcard.

Keterbatasan

Indeks kartu bebas tidak mendukung apa pun dari jenis atau properti indeks berikut:

  • Compound

  • TTL

  • Unik

  • Tidak seperti di MongoDB, di Azure Cosmos DB untuk MongoDB Anda tidak dapat menggunakan indeks wildcard untuk:

  • Membuat indeks wildcard yang menyertakan beberapa bidang spesifik

    db.coll.createIndex(
      { "$**" : 1 },
      { "wildcardProjection " :
        {
          "children.givenName" : 1,
          "children.grade" : 1
        }
      }
    )
    
  • Membuat indeks wildcard yang mengeluarkan beberapa bidang tertentu

    db.coll.createIndex(
      { "$**" : 1 },
      { "wildcardProjection" :
        {
          "children.givenName" : 0,
          "children.grade" : 0
        }
      }
    )
    

Sebagai alternatif, buat beberapa indeks wildcard.

Properti indeks

Operasi berikut umum untuk akun yang menggunakan protokol kawat versi 4.0 dan versi yang lebih lama. Pelajari selengkapnya tentang indeks dan properti terindeks yang didukung.

Indeks unik

Indeks unik membantu memastikan bahwa dua dokumen atau lebih tidak memiliki nilai yang sama untuk bidang terindeks.

Jalankan perintah berikut untuk membuat indeks unik di student_id bidang :

db.coll.createIndex( { "student_id" : 1 }, {unique:true} )

{
  "_t" : "CreateIndexesResponse",
  "ok" : 1,
  "createdCollectionAutomatically" : false,
  "numIndexesBefore" : 1,
  "numIndexesAfter" : 4
}

Untuk koleksi yang terpecah, sediakan kunci pecahan atau kunci partisi untuk membuat indeks unik. Semua indeks unik pada koleksi pecahan adalah indeks gabungan, dan salah satu bidangnya adalah kunci shard. Kunci shard harus menjadi bidang pertama dalam definisi indeks.

Jalankan perintah berikut untuk membuat koleksi terpartisi bernama coll (dengan university sebagai kunci shard) dan indeks unik pada bidang student_id dan university.

db.runCommand({shardCollection: db.coll._fullName, key: { university: "hashed"}});
{
  "_t" : "ShardCollectionResponse",
  "ok" : 1,
  "collectionsharded" : "test.coll"
}
db.coll.createIndex( { "university" : 1, "student_id" : 1 }, {unique:true});
{
  "_t" : "CreateIndexesResponse",
  "ok" : 1,
  "createdCollectionAutomatically" : false,
  "numIndexesBefore" : 3,
  "numIndexesAfter" : 4
}

Jika Anda menghilangkan "university":1 klausul dalam contoh sebelumnya, Anda akan melihat pesan kesalahan berikut:

cannot create unique index over {student_id : 1.0} with shard key pattern { university : 1.0 }

Keterbatasan

Buat indeks unik saat koleksi kosong.

Akun Azure Cosmos DB untuk MongoDB dengan pencadangan berkelanjutan tidak mendukung pembuatan indeks unik untuk koleksi yang ada. Untuk akun seperti itu, indeks unik harus dibuat bersamaan dengan pembuatan koleksi mereka, yang harus dan hanya dapat dilakukan menggunakan perintah ekstensi untuk membuat koleksi.

db.runCommand({customAction:"CreateCollection", collection:"coll", shardKey:"student_id", indexes:[
{key: { "student_id" : 1}, name:"student_id_1", unique: true}
]});

Indeks unik pada bidang berlapis tidak didukung secara default karena keterbatasan dengan array. Jika bidang berlapis Anda tidak memiliki array, indeks berfungsi seperti yang dimaksudkan. Jika bidang berlapis Anda memiliki array di mana saja di jalur, nilai tersebut diabaikan dalam indeks unik tersebut, dan keunikan nilai tersebut tidak dipertahankan.

Misalnya, indeks unik pada people.tom.age berfungsi dalam kasus ini karena tidak ada array pada jalur:

{
  "people": {
    "tom": {
      "age": "25"
    },
    "mark": {
      "age": "30"
    }
  }
}

Tetapi tidak berfungsi dalam kasus ini karena ada array di jalur:

{
  "people": {
    "tom": [
      {
        "age": "25"
      }
    ],
    "mark": [
      {
        "age": "30"
      }
    ]
  }
}

Fitur ini dapat diaktifkan untuk akun database Anda dengan mengaktifkan kemampuan 'EnableUniqueCompoundNestedDocs'.

Indeks TTL

Untuk membiarkan dokumen kedaluwarsa di dalam kumpulan, buat indeks time-to-live (TTL). Indeks TTL adalah indeks pada bidang _ts dengan nilai expireAfterSeconds.

Contoh:

db.coll.createIndex({"_ts":1}, {expireAfterSeconds: 10})

Perintah sebelumnya menghapus dokumen apa pun dalam db.coll koleksi yang dimodifikasi lebih dari 10 detik yang lalu.

Nota

Bidang _ts khusus untuk Azure Cosmos DB dan tidak dapat diakses dari klien MongoDB. Ini adalah properti cadangan sistem yang berisi stempel waktu modifikasi terakhir dokumen.

Lacak kemajuan indeks

Azure Cosmos DB for MongoDB versi 3.6+ mendukung currentOp() perintah untuk melacak kemajuan indeks pada instans database. Perintah ini mengembalikan dokumen dengan informasi tentang operasi yang sedang berlangsung pada instans database. currentOp Gunakan perintah untuk melacak semua operasi yang sedang berlangsung di MongoDB asli. Di Azure Cosmos DB untuk MongoDB, perintah ini hanya melacak operasi indeks.

Berikut adalah beberapa contoh cara menggunakan currentOp perintah untuk melacak kemajuan indeks:

  • Dapatkan kemajuan indeks untuk koleksi:

    db.currentOp({"command.createIndexes": <collectionName>, "command.$db": <databaseName>})
    
  • Dapatkan kemajuan indeks untuk semua koleksi dalam database:

    db.currentOp({"command.$db": <databaseName>})
    
  • Dapatkan kemajuan indeks untuk semua database dan koleksi di akun Azure Cosmos DB:

    db.currentOp({"command.createIndexes": { $exists : true } })
    

Contoh output kemajuan indeks

Detail kemajuan indeks menunjukkan persentase kemajuan untuk operasi indeks saat ini. Berikut adalah contoh format dokumen output untuk berbagai tahap kemajuan indeks:

  • Operasi indeks pada koleksi "foo" dan basis data "bar" yang telah 60 persen selesai memiliki dokumen keluaran berikut. Bidang Inprog[0].progress.total menunjukkan 100 sebagai persentase penyelesaian target.

    {
      "inprog": [
        {
          ...
          "command": {
            "createIndexes": foo
            "indexes": [],
            "$db": bar
          },
          "msg": "Index Build (background) Index Build (background): 60 %",
          "progress": {
            "done": 60,
            "total": 100
          },
          ...
        }
      ],
      "ok": 1
    }
    
  • Jika operasi indeks baru saja dimulai pada koleksi "foo" dan database "bar", dokumen output dapat menunjukkan 0 persen kemajuan sampai mencapai tingkat yang terukur.

    {
      "inprog": [
        {
          ...
          "command": {
            "createIndexes": foo
            "indexes": [],
            "$db": bar
          },
          "msg": "Index Build (background) Index Build (background): 0 %",
          "progress": {
            "done": 0,
            "total": 100
          },
          ...
        }
      ],
      "ok": 1
    }
    
  • Ketika operasi indeks selesai, dokumen output menunjukkan operasi kosong inprog .

    {
      "inprog" : [],
      "ok" : 1
    }
    

Pembaruan indeks latar belakang

Pembaruan indeks selalu berjalan di latar belakang, apa pun nilai yang Anda tetapkan untuk properti Indeks latar belakang . Karena pembaruan indeks menggunakan Unit Permintaan (RU) dengan prioritas yang lebih rendah daripada tindakan database lainnya, perubahan indeks tidak menyebabkan waktu henti untuk menulis, memperbarui, atau menghapus.

Menambahkan indeks baru tidak memengaruhi ketersediaan baca. Kueri menggunakan indeks baru hanya setelah transformasi indeks selesai. Selama transformasi, mesin kueri terus menggunakan indeks yang ada, sehingga Anda melihat performa baca yang sama seperti sebelum Anda memulai perubahan pengindeksan. Menambahkan indeks baru tidak berisiko tidak lengkap atau hasil kueri yang tidak konsisten.

Jika Anda menghapus indeks dan segera menjalankan kueri yang memfilter indeks yang dihilangkan, hasilnya bisa tidak konsisten dan tidak lengkap sampai transformasi indeks selesai. Mesin kueri tidak memberikan hasil yang konsisten atau lengkap untuk kueri yang memfilter indeks yang baru dihapus. Sebagian besar pengembang tidak menghilangkan indeks dan kemudian segera mengkuerinya, sehingga situasi ini tidak mungkin terjadi.

Nota

Anda dapat melacak progres indeks.

reIndex perintah

Perintah reIndex membuat ulang semua indeks pada koleksi. Dalam kasus yang jarang terjadi, menjalankan reIndex perintah dapat memperbaiki performa kueri atau masalah indeks lainnya dalam koleksi Anda. Jika Anda mengalami masalah pengindeksan, coba buat ulang indeks dengan reIndex perintah .

Jalankan reIndex perintah menggunakan sintaks berikut:

db.runCommand({ reIndex: <collection> })

Gunakan sintaks berikut untuk memeriksa apakah menjalankan reIndex perintah meningkatkan performa kueri dalam koleksi Anda:

db.runCommand({"customAction":"GetCollection",collection:<collection>, showIndexes:true})

Contoh output:

{
  "database": "myDB",
  "collection": "myCollection",
  "provisionedThroughput": 400,
  "indexes": [
    {
      "v": 1,
      "key": {
        "_id": 1
      },
      "name": "_id_",
      "ns": "myDB.myCollection",
      "requiresReIndex": true
    },
    {
      "v": 1,
      "key": {
        "b.$**": 1
      },
      "name": "b.$**_1",
      "ns": "myDB.myCollection",
      "requiresReIndex": true
    }
  ],
  "ok": 1
}

Jika reIndex meningkatkan performa kueri, requiresReIndex bernilai benar. Jika reIndex tidak meningkatkan performa kueri, properti ini dihilangkan.

Melakukan migrasi koleksi dengan indeks

Anda hanya dapat membuat indeks unik saat koleksi tidak memiliki dokumen. Alat migrasi MongoDB populer mencoba membuat indeks unik setelah mengimpor data. Untuk mengatasi masalah ini, buat koleksi dan indeks unik yang sesuai secara manual alih-alih membiarkan alat migrasi mencoba. Anda mencapai perilaku ini dengan menggunakan flag mongorestore pada --noIndexRestore di baris perintah.

Pengindeksan untuk MongoDB versi 3.2

Fitur pengindeksan dan default berbeda untuk akun Azure Cosmos DB yang menggunakan protokol kawat MongoDB versi 3.2. Periksa versi akun Anda di feature-support-36.md#protocol-support, dan tingkatkan ke versi 3.6 di upgrade-version.md.

Jika Anda menggunakan versi 3.2, bagian ini menyoroti perbedaan utama dari versi 3.6 dan yang lebih baru.

Menghapus indeks default (versi 3.2)

Tidak seperti versi 3.6 dan yang lebih baru, Azure Cosmos DB untuk MongoDB versi 3.2 mengindeks setiap properti secara default. Gunakan perintah berikut untuk menghilangkan indeks default ini untuk koleksi (coll):

db.coll.dropIndexes()
{ "_t" : "DropIndexesResponse", "ok" : 1, "nIndexesWas" : 3 }

Setelah Anda menghilangkan indeks default, tambahkan lebih banyak indeks seperti yang Anda lakukan di versi 3.6 dan yang lebih baru.

Indeks campuran (versi 3.2)

Indeks gabungan mereferensikan beberapa bidang dalam dokumen. Untuk membuat indeks gabungan, tingkatkan ke versi 3.6 atau 4.0 pada upgrade-version.md.

Indeks pengganti karakter (versi 3.2)

Untuk membuat indeks kartu bebas, tingkatkan ke versi 4.0 atau 3.6 di upgrade-version.md.

Langkah berikutnya