Mengelola pengindeksan di Azure Cosmos DB untuk MongoDB

BERLAKU UNTUK: MongoDB

Azure Cosmos DB for MongoDB memanfaatkan kemampuan manajemen indeks inti Azure Cosmos DB. Artikel ini berfokus pada cara menambahkan indeks menggunakan Azure Cosmos DB untuk MongoDB. Indeks adalah struktur data khusus yang membuat penguerian data Anda secara kira-kira berdasarkan urutan besarnya lebih cepat.

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 shard (hanya dalam koleksi pecahan). API secara otomatis memberlakukan keunikan bidang _id per kunci shard.

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

Memperbarui kebijakan pengindeksan

Sebaiknya edit kebijakan pengindeksan Anda di Data Explorer dalam portal Microsoft Azure. Anda bisa menambahkan indeks bidang tunggal dan kartubebas dari editor kebijakan pengindeksan di Data Explorer:

Indexing policy editor

Catatan

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

Jenis indeks

Bidang tunggal

Anda dapat membuat indeks pada bidang tunggal apa pun. Susunan urutan indeks bidang tunggal tidak masalah. Perintah berikut membuat indeks pada bidang name:

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

Anda dapat membuat indeks bidang tunggal yang sama name di portal Microsoft Azure:

Add name index in indexing policy editor

Satu kueri menggunakan beberapa indeks bidang tunggal jika tersedia. Anda dapat membuat hingga 500 indeks bidang tunggal per koleksi.

Indeks campuran (server MongoDB versi 3.6+)

Di API untuk MongoDB, indeks gabungan diperlukan jika kueri Anda memerlukan kemampuan untuk 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 Anda tidak berisi array, indeks berfungsi seperti yang dimaksudkan. Jika bidang berlapis Anda berisi array (di mana saja di jalur), nilai tersebut diabaikan dalam indeks.

Sebagai contoh, indeks gabungan yang berisi people.dylan.age pekerjaan dalam kasus ini karena tidak ada array di jalur:

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

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

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

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

Catatan

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 contohnya:

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

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

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

Index Multikunci

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

Indeks geospasial

Banyak operator geospasial akan mendapat manfaat dari indeks geospasial. Saat ini, 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 saat ini tidak mendukung indeks teks. Untuk kueri pencarian teks pada string, Anda harus menggunakan integrasi Azure AI Search dengan Azure Cosmos DB.

Indeks kartubebas

Anda dapat menggunakan indeks kartubebas untuk mendukung kueri terhadap bidang tidak dikenal. Kita bayangkan Anda memiliki koleksi yang menyimpan data keluarga.

Berikut adalah bagian dari contoh dokumen dalam koleksi tersebut:

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

Berikut contoh lainnya, kali ini dengan sekumpulan properti yang agak berbeda di children:

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

Dalam koleksi ini, dokumen dapat memiliki banyak properti yang mungkin berbeda. Jika Anda ingin mengindeks semua data dalam children array, Anda memiliki dua opsi: membuat indeks terpisah untuk setiap properti individual atau membuat satu indeks kartubebas untuk seluruh children array.

Membuat indeks kartubebas

Perintah berikut membuat indeks kartubebas pada properti apa pun di dalam children:

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

Tidak seperti di MongoDB, indeks kartubebas dapat mendukung beberapa bidang dalam predikat kueri. Di dalam performa kueri tidak akan ada perbedaan jika Anda menggunakan satu indeks kartubebas tunggal alih-alih membuat indeks terpisah untuk setiap properti.

Anda dapat membuat jenis indeks berikut menggunakan sintaks kartubebas:

  • Bidang tunggal
  • Geospasial

Mengindeks semua properti

Berikut cara membuat indeks kartubebas di semua bidang:

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

Anda juga dapat membuat indeks kartubebas menggunakan Data Explorer di portal Microsoft Azure:

Add wildcard index in indexing policy editor

Catatan

Jika Anda baru memulai pengembangan, kami sangat menyarankan untuk memulai dengan indeks kartubebas di semua bidang. Langkah ini dapat menyederhanakan pengembangan dan mempermudah pengoptimalan kueri.

Dokumen dengan banyak bidang mungkin memiliki biaya Unit Permintaan (RU) yang tinggi untuk penulisan dan pembaruan. Oleh karena itu, jika Anda memiliki beban kerja tulis yang berat, Anda harus memilih untuk secara individual mengindeks jalur dibandingkan menggunakan indeks kartubebas.

Catatan

Dukungan untuk indeks unik pada koleksi yang ada dengan data, tersedia dalam pratinjau. Fitur ini dapat diaktifkan untuk akun database Anda dengan mengaktifkan kemampuan 'EnableUniqueIndexReIndex'.

Batasan

Indeks kartubebas tidak mendukung jenis atau properti indeks berikut:

  • Campuran
  • TTL
  • Unik

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

  • Membuat indeks kartubebas yang menyertakan beberapa bidang tertentu

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

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

Atau, Anda dapat membuat beberapa indeks kartubebas.

Properti indeks

Operasi berikut umum untuk akun yang melayani protokol kabel versi 4.0 dan akun yang melayani versi yang lebih lama. Anda dapat mempelajari selengkapnya tentang indeks yang didukung dan properti terindeks.

Indeks unik

Indeks unik berguna untuk memberlakukan bahwa dua dokumen atau lebih tidak berisi nilai yang sama untuk bidang terindeks.

Perintah berikut membuat indeks unik pada bidang student_id:

globaldb:PRIMARY> db.coll.createIndex( { "student_id" : 1 }, {unique:true} )
{
    "_t" : "CreateIndexesResponse",
    "ok" : 1,
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 4
}

Untuk koleksi pecahan, Anda harus menyediakan kunci pecahan (partisi) untuk membuat indeks unik. Dengan kata lain, semua indeks unik pada koleksi pecahan adalah indeks gabungan di mana salah satu bidang adalah kunci shard. Bidang pertama dalam urutan harus berupa kunci shard.

Perintah berikut membuat koleksi pecahan coll (kunci pecahan adalah university) dengan indeks unik pada bidang student_id dan university:

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

Dalam contoh sebelumnya, menghilangkan "university":1 klausa menampilkan kesalahan dengan pesan berikut:

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

Batasan

Indeks unik perlu dibuat saat koleksi kosong.

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

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

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

tetapi tidak akan 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 mengaktifkan kedaluwarsa dokumen dalam koleksi tertentu, Anda perlu membuat indeks time-to-live (TTL). Indeks TTL adalah indeks pada _ts bidang dengan expireAfterSeconds nilai.

Contoh:

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

Perintah sebelumnya menghapus dokumen apa pun dalam db.coll koleksi yang belum dimodifikasi dalam 10 detik terakhir.

Catatan

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

Lacak progres indeks

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

Berikut adalah beberapa contoh yang memperlihatkan cara menggunakan currentOp perintah untuk melacak progres indeks:

  • Dapatkan progres indeks untuk koleksi:

    db.currentOp({"command.createIndexes": <collectionName>, "command.$db": <databaseName>})
    
  • Dapatkan progres 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 progres indeks

Detail progres indeks memperlihatkan persentase progres untuk operasi indeks saat ini. Berikut adalah contoh yang memperlihatkan format dokumen output untuk berbagai tahap progres indeks:

  • Operasi indeks pada koleksi "foo" dan database "bar" yang 60 persen selesai akan memiliki dokumen output 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 mungkin menunjukkan progres 0 persen hingga mencapai tingkat terukur.

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

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

Pembaruan indeks latar belakang

Terlepas dari nilai yang ditentukan untuk properti indeks Latar Belakang, pembaruan indeks selalu dilakukan di latar belakang. Karena pembaruan indeks memakai Unit Permintaan (RUs) pada prioritas yang lebih rendah dibandingkan operasi database lainnya, perubahan indeks tidak akan menyebabkan waktu henti untuk menulis, memperbarui, atau menghapus.

Tidak ada dampak untuk membaca ketersediaan saat menambahkan indeks baru. Kueri hanya akan menggunakan indeks baru setelah transformasi indeks selesai. Selama transformasi indeks, mesin kueri akan terus menggunakan indeks yang ada, sehingga Anda akan mengamati performa baca yang sama selama transformasi pengindeksan dengan apa yang telah Anda amati sebelum memulai perubahan pengindeksan. Saat menambahkan indeks baru, juga tidak ada risiko hasil kueri yang tidak lengkap atau tidak konsisten.

Saat menghapus indeks dan segera menjalankan kueri yang memiliki filter pada indeks yang dihilangkan, hasilnya mungkin tidak konsisten dan tidak lengkap sampai transformasi indeks selesai. Jika Anda menghapus indeks, mesin kueri tidak memberikan hasil yang konsisten atau lengkap saat kueri memfilter indeks yang baru dihilangkan ini. Sebagian besar pengembang tidak menghilangkan indeks dan kemudian langsung mencoba untuk memintanya, sehingga dalam praktiknya, situasi ini tidak mungkin terjadi.

Catatan

Anda dapat melacak progres indeks.

Perintah ReIndex

Perintah reIndex akan membuat ulang semua indeks pada sebuah koleksi. Dalam beberapa kasus yang jarang terjadi, performa kueri atau masalah indeks lainnya dalam kumpulan Anda dapat diselesaikan dengan menjalankan perintah reIndex. Jika Anda mengalami masalah dengan pengindeksan, membuat ulang indeks dengan perintah reIndex adalah pendekatan yang disarankan.

Anda bisa menjalankan reIndex perintah menggunakan sintaks berikut:

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

Anda dapat menggunakan sintaks di bawah untuk memeriksa apakah perintah reIndex akan meningkatkan performa kueri dalam kumpulan 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 akan meningkatkan performa kueri, requiresReIndex akan menjadi true (benar). Jika reIndex tidak akan meningkatkan performa kueri, properti ini akan dihilangkan.

Melakukan migrasi koleksi dengan indeks

Saat ini, Anda hanya dapat membuat indeks unik saat koleksi tidak berisi dokumen. Alat migrasi MongoDB populer mencoba membuat indeks unik setelah mengimpor data. Untuk menghindari masalah ini, Anda dapat membuat koleksi dan indeks unik secara manual, dan bukan mengizinkan alat migrasi untuk mencoba. (Anda dapat mencapai perilaku ini mongorestore dengan menggunakan --noIndexRestore bendera di baris perintah.)

Pengindeksan untuk MongoDB versi 3.2

Fitur dan default pengindeksan yang tersedia berbeda untuk akun Azure Cosmos DB yang kompatibel dengan protokol kawat MongoDB versi 3.2. Anda dapat memeriksa versi akun Anda dan meningkatkan ke versi 3.6.

Jika Anda menggunakan versi 3.2, bagian ini menguraikan perbedaan utama dengan versi 3.6+.

Menghilangkan indeks default (versi 3.2)

Tidak seperti Versi 3.6+ Azure Cosmos DB untuk MongoDB, versi 3.2 mengindeks setiap properti secara default. Anda dapat menggunakan perintah berikut untuk menghilangkan indeks default ini untuk koleksi (coll):

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

Setelah menghilangkan indeks default, Anda dapat menambahkan lebih banyak indeks seperti yang Anda lakukan di versi 3.6+.

Indeks campuran (versi 3.2)

Indeks campuran menyimpan referensi ke beberapa bidang dokumen. Jika Anda ingin membuat indeks campuran, tingkatkan ke versi 3.6 atau 4.0.

Indeks kartubebas (versi 3.2)

Jika Anda ingin membuat indeks kartubebas, tingkatkan ke versi 4.0 atau 3.6.

Langkah berikutnya