Indeks perlu mencakup semua bagian kueri (bagian kesetaraan, bagian pengurutan, dan bagian rentang). Ini karena dalam tipikal find()
query, MongoDB hanya menggunakan satu indeks. Misalnya, umumnya tidak menggunakan satu indeks untuk bagian kesetaraan, dan indeks lain untuk bagian pengurutan.
Secara umum, urutan kolom dalam indeks harus mengikuti pola equality -> sort -> range .
Ini dijelaskan secara mendetail di Mengoptimalkan Indeks Senyawa MongoDB .
Untuk kueri Anda, bagian kesetaraan adalah tag:..., letterId:...
dan bagian pengurutannya adalah emailId:-1
. Tidak ada bagian rentang dalam kueri Anda.
Dengan menggunakan pola ini, indeks gabungan yang Anda butuhkan adalah:
db.test.createIndex({tag:1, letterId:1, emailId:-1})
Mari kita coba untuk memastikan seberapa besar peningkatan kinerja yang dapat kita peroleh dengan menggunakan indeks ini.
Data uji
Untuk mengonfirmasi kesesuaian indeks, saya memasukkan 1 juta catatan ke dalam database pengujian menggunakan mgeneratejs , yang merupakan alat untuk membuat dokumen acak menggunakan template.
Berdasarkan contoh Anda, mgeneratejs
template yang saya gunakan adalah:
$ cat template.json
{
"emailId": "$hash",
"email": "$email",
"letterId": "$hash",
"sendedFrom": "$email",
"resultMsg": "$word",
"owner": "$name",
"created": "$date",
"result": "$bool",
"tag": "$word",
"tryNum": {"$integer": {"min": 0, "max": 1e3}},
"clickHash": "$word",
"links": {"$array": {"of": "$url", "number": {"$integer": {"min": 1, "max": 5}}}}
}
dan mengimpor 1 juta dokumen acak ke MongoDB:
$ mgeneratejs template.json -n 1000000 | mongoimport -d test -c test
Uji 1:indeks tidak optimal
Kemudian saya membuat indeks yang Anda miliki, dan mencoba menemukan dokumen yang tidak ada dan mengumpulkan 10 kueri dengan koleksi yang hanya berisi indeks ini:
> db.test.createIndex({emailId: 1, letterId: 1, result: 1, owner: 1, tag: 1, clickHash: 1})
> db.test.find({"tag" : "xyz", "letterId" : "abc"}).sort({emailId: -1}).limit(1)
Fetched 0 record(s) in 3069ms
Fetched 0 record(s) in 2924ms
Fetched 0 record(s) in 2923ms
Fetched 0 record(s) in 3013ms
Fetched 0 record(s) in 2917ms
Fetched 0 record(s) in 2961ms
Fetched 0 record(s) in 2882ms
Fetched 0 record(s) in 2870ms
Fetched 0 record(s) in 2969ms
Fetched 0 record(s) in 2863ms
jadi menggunakan indeks itu, waktu respons kueri tidak bagus, dengan sebagian besar eksekusi mendekati 3 detik.
Tes 2:kesetaraan -> sortir -> indeks rentang
Dengan menambahkan kesetaraan -> sortir -> rentang optimal yang optimal indeks:
> db.test.createIndex({tag:1, letterId:1, emailId:-1})
> db.test.find({"tag" : "xyz", "letterId" : "abc"}).sort({emailId: -1}).limit(1)
Fetched 0 record(s) in 2ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 3ms
Sebaliknya, dengan menggunakan indeks optimal, kinerja meningkat secara nyata. Tidak ada kueri yang dikembalikan dalam waktu lebih dari 3 md, dengan sebagian besar waktu kueri kembali dalam 1 md.