Ukuran indeks mongodb terlalu besar

Setiap indeks menempati beberapa ruang serta menyebabkan overhead pada setiap penyisipan, pembaruan, dan penghapusan. Jadi, jika Anda jarang menggunakan koleksi Anda untuk operasi baca, masuk akal untuk tidak menggunakan indeks

Penggunaan RAM

Karena indeks disimpan dalam RAM, Anda harus memastikan bahwa ukuran total indeks tidak melebihi batas RAM. Jika ukuran total meningkatkan ukuran RAM, itu akan mulai menghapus beberapa indeks, menyebabkan hilangnya kinerja

Keterbatasan Kueri

Pengindeksan tidak dapat digunakan dalam kueri yang menggunakan −

  • Ekspresi reguler atau operator negasi seperti $nin, $not, dll
  • Operator aritmatika seperti $mod, dll
  • $di mana klausa

Oleh karena itu, selalu disarankan untuk memeriksa penggunaan indeks untuk kueri Anda

Batas Kunci Indeks

Mulai dari versi 2. 6, MongoDB tidak akan membuat indeks jika nilai bidang indeks yang ada melebihi batas kunci indeks

Memasukkan Dokumen yang Melebihi Batas Kunci Indeks

MongoDB tidak akan memasukkan dokumen apa pun ke dalam koleksi yang diindeks jika nilai bidang yang diindeks dari dokumen ini melebihi batas kunci indeks. Sama halnya dengan mongorestore dan mongoimport utilitas

Perbedaan antara aplikasi Anda yang cepat, responsif, dan penskalaan dengan benar seringkali bergantung pada cara Anda menggunakan indeks di database. MongoDB tidak berbeda, kinerjanya (dan keseluruhan kinerja aplikasi Anda) sangat bergantung pada mendapatkan jumlah indeks yang tepat pada hal yang benar. Satu atau dua indeks sederhana dapat mempercepat pengambilan data dari MongoDB jutaan kali lipat untuk tabel jutaan catatan. Tetapi pada saat yang sama memiliki terlalu banyak indeks pada koleksi besar dapat menyebabkan penurunan besar-besaran dalam kinerja secara keseluruhan. Anda perlu mendapatkan indeks Anda dengan benar

Untuk blog ini, kita akan berbicara tentang memiliki terlalu banyak indeks dan membantu Anda menemukan indeks duplikat dan tidak terpakai. Jika Anda tertarik untuk mengetahui apakah Anda memerlukan indeks tambahan atau jika kueri Anda menggunakan indeks, saya sarankan membaca artikel Percona sebelumnya tentang penyetelan kueri (Bagian 1 & Bagian 2 dari seri itu)

Jadi, indeks sangat bagus untuk mendapatkan kueri yang lebih cepat. Berapa banyak indeks yang harus saya buat pada koleksi?

Masalah Kinerja Umum

Setelah menganalisis banyak lingkungan MongoDB yang berbeda, saya dapat memberikan daftar berikut yang meringkas kesalahan umum yang saya lihat

  • Tidak membuat indeks sama sekali, selain _id kunci utama yang dibuat oleh desain
    • Saya tidak bercanda – saya telah melihat database tanpa indeks yang dibuat oleh pengguna, yang membuat pemilik terkejut karena server kelebihan beban dan/atau kueri menjadi sangat lambat
  • Mengindeks koleksi secara berlebihan
    • Beberapa pengembang biasanya membuat banyak indeks tanpa alasan tertentu atau hanya untuk menguji kueri. Kemudian mereka lupa untuk menjatuhkannya
    • Dalam beberapa kasus, ukuran semua indeks lebih besar dari data. Ini tidak bagus;

Saya tidak mempertimbangkan kasus pertama. Saya akan membahas yang kedua

Berapa Banyak Indeks yang Anda Butuhkan dalam Koleksi

Itu tergantung - itu jawaban yang tepat. Pada dasarnya, itu tergantung pada beban kerja aplikasi Anda. Anda harus mempertimbangkan aturan berikut saat mengindeks koleksi

  • Buat indeks sebanyak mungkin untuk aplikasi Anda
  • Jangan membuat banyak indeks

Apa? . Nah, kita bisa meringkas hanya dalam satu aturan sederhana

  • Anda perlu membuat semua indeks yang benar-benar dibutuhkan aplikasi Anda untuk menyelesaikan kueri yang paling sering. Tidak satu lagi, tidak kurang satu pun

Itu dia

Pro dan Kontra Pengindeksan

Keuntungan besar dari indeks adalah memungkinkan kueri, pembaruan, dan penghapusan berjalan secepat mungkin jika digunakan. (Setiap pembaruan atau penghapusan juga perlu melakukan langkah pencarian terlebih dahulu). Lebih banyak indeks dalam koleksi dapat menguntungkan beberapa kueri

Sayangnya, indeks membutuhkan kerja ekstra untuk MongoDB. Setiap kali Anda menjalankan penulisan, semua indeks harus diperbarui. Nilai-nilai baru disimpan atau dijatuhkan ke dalam struktur B-Tree, beberapa pemisahan atau penggabungan diperlukan, dan ini membutuhkan waktu

Masalah utama adalah bahwa "lebih banyak indeks yang Anda miliki dalam koleksi, semakin lambat semua penulisan"

Koleksi yang sangat besar dengan hanya 10 atau 15 indeks dapat menyebabkan penurunan performa yang signifikan untuk penulisan. Juga, ingat bahwa indeks harus disalin ke dalam cache WiredTiger. Lebih banyak indeks juga menyiratkan lebih banyak tekanan untuk cache memori. Tekanan kemudian dapat menyebabkan lebih banyak pengusiran dan kelambatan cache

Contoh bagusnya adalah ketika saya bekerja dengan pelanggan beberapa minggu yang lalu kami menemukan 12 indeks tambahan pada koleksi yang tidak mereka perlukan. Koleksinya sekitar 80GB; . Mereka memiliki beban tulis yang relevan berdasarkan beberapa penyisipan dan pembaruan yang sering dilakukan setiap saat. Membersihkan indeks ini meningkatkan waktu eksekusi kueri tulis rata-rata sebesar 25-30 persen. Peningkatan yang diamati untuk kasus nyata ini tidak akan menjadi jumlah kuantitatif yang sama dalam kasus lain, tetapi yang pasti semakin sedikit indeks yang Anda miliki, semakin cepat semua penulisan akan dilakukan.

Kita perlu menemukan semacam keseimbangan. membuat lebih banyak indeks, tetapi tidak sebanyak itu

Cara Mengurangi Over-Indexing

Sangat mudah untuk mengatakannya. jatuhkan semua indeks yang tidak Anda butuhkan

Ada dua hal yang dapat Anda lakukan untuk mengidentifikasi indeks yang akan dijatuhkan

  • Periksa duplikatnya
  • Periksa indeks yang tidak digunakan

Untuk menjatuhkan indeks, Anda perlu menjalankan sesuatu seperti berikut ini

Kerang

1

db. koleksi saya. dropIndex("nama_indeks")

Temukan Indeks Duplikat

Indeks duplikat bisa berupa indeks dengan definisi yang persis sama dengan indeks lain yang sudah ada dalam koleksi. Untungnya, MongoDB dapat memeriksa ini dan tidak diizinkan membuat indeks semacam itu

Mari kita lakukan pengujian menggunakan koleksi sederhana tanpa indeks

Kerang

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

rs_test. UTAMA> db. tes. temukan()

{ "_id" . ObjectId("60521309d7268c122c7cd630"), "name" : "corrado", "usia" . 49 }

{ "_id" . ObjectId("60521313d7268c122c7cd631"), "name" : "simone", "usia" . 12 }

{ "_id" . ObjectId("6052131cd7268c122c7cd632"), "name" : "gabriele", "umur" . 19 }

{ "_id" . ObjectId("60521323d7268c122c7cd633"), "name" : "luca", "umur" . 14 }

{ "_id" . ObjectId("60521328d7268c122c7cd634"), "name" : "lucia", "usia" . 49 }

 

# buat indeks pada bidang nama

rs_test. UTAMA> db. tes. createIndex( { nama. 1 } )

{

   "dibuatKoleksiOtomatis" . salah,

   "numIndexesBefore" . 1,

   "numIndexesAfter" . 2,

   "commitQuorum" . "memilih Anggota",

   "oke" . 1,

   "$clusterTime" . {

      "clusterTime" . Stempel waktu(1615991942, 5),

      "tanda tangan" . {

         "hash" . BinData(0,"),

         "keyId" . NumberLong("6890926313742270469")

      }

   },

   "Waktu Operasi" . Stempel waktu(1615991942, 5)

}

 

# periksa indeks tersedia

rs_test. UTAMA> db. tes. getIndex()

[

   {

      "v" . 2,

      "kunci" . {

         "_id" . 1

      },

      "nama" . "_id_"

   },

   {

      "v" . 2,

      "kunci" . {

         "nama" . 1

      },

      "nama" . "nama_1"

   }

]

 

# coba buat lagi indeks yang sama

rs_test. UTAMA> db. tes. createIndex( { nama. 1 } )

{

   "numIndexesBefore" . 2,

   "numIndexesAfter" . 2,

   "catatan" . "semua indeks sudah ada",

   "oke" . 1,

   "$clusterTime" . {

      "clusterTime" . Stempel waktu(1615991942, 5),

      "tanda tangan" . {

         "hash" . BinData(0,"),

         "keyId" . NumberLong("6890926313742270469")

      }

   },

   "Waktu Operasi" . Stempel waktu(1615991942, 5)

}

 

# hebat, MongoDB dapat mendeteksi indeks yang sudah ada

 

# mari kita coba untuk melihat apakah Anda dapat membuat indeks yang sama dengan nama yang berbeda

rs_test. UTAMA> db. tes. createIndex( { nama. 1 }, { nama . : "this_is_a_different_index_name" } )

{

   "Waktu Operasi" . Stempel waktu(1615991981, 1),

   "oke" . 0,

   "errmsg" . "Indeks dengan nama. this_is_a_different_index_name sudah ada dengan nama yang berbeda",

   "kode" . 85,

   "codeName" . "IndexOptionsConflict",

   "$clusterTime" . {

      "clusterTime" . Stempel waktu(1615991981, 1),

      "tanda tangan" . {

         "hash" . BinData(0,"),

         "keyId" . NumberLong("6890926313742270469")

      }

   }

}

 

# bahkan dalam hal ini MongoDB tidak mengizinkan pembuatan indeks

MongoDB kemudian cukup pintar untuk menghindari pembuatan indeks duplikat. Tapi bagaimana dengan pembuatan indeks yang merupakan awalan kiri dari indeks yang ada?

Kerang

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

# mari kita jatuhkan indeks sebelumnya yang telah kita buat

rs_test. UTAMA> db. tes. dropIndex( "nama_1" )

{

   "nIndexesWas" . 2,

   "oke" . 1,

   "$clusterTime" . {

      "clusterTime" . Stempel waktu(1615993029, 1),

      "tanda tangan" . {

         "hash" . BinData(0,"),

         "keyId" . NumberLong("6890926313742270469")  

      }

   },

   "Waktu Operasi" . Stempel waktu(1615993029, 1)

}

 

# periksa indeks. Hanya _id yang tersedia

rs_test. UTAMA> db. tes. getIndex()

[ { "v" . 2, "kunci" . { "_id" . 1 }, "nama" : "_id_" } ]

 

# buat indeks majemuk

rs_test. UTAMA> db. tes. createIndex( { nama. 1, umur. 1 } )

{

   "dibuatKoleksiOtomatis" . salah,

   "numIndexesBefore" . 1,

   "numIndexesAfter" . 2,

   "commitQuorum" . "memilih Anggota",

   "oke" . 1,

   "$clusterTime" . {

      "clusterTime" . Stempel waktu(1615993054, 5),

      "tanda tangan" . {

         "hash" . BinData(0,"),

         "keyId" . NumberLong("6890926313742270469")

      }

   },

   "Waktu Operasi" . Stempel waktu(1615993054, 5)

}

 

# buat indeks lain yang merupakan awalan paling kiri dari indeks majemuk

rs_test. UTAMA> db. tes. createIndex( { nama. 1 } )

{

   "dibuatKoleksiOtomatis" . salah,

   "numIndexesBefore" . 2,

   "numIndexesAfter" . 3,

   "commitQuorum" . "memilih Anggota",

   "oke" . 1,

   "$clusterTime" . {

      "clusterTime" . Stempel waktu(1615993060, 5),

      "tanda tangan" . {

         "hash" . BinData(0,"),

         "keyId" . NumberLong("6890926313742270469")

      }

   },

   "Waktu Operasi" . Stempel waktu(1615993060, 5)

}

 

# periksa indeks

rs_test. UTAMA> db. tes. getIndex()

[

   {

      "v" . 2,

      "kunci" . {

         "_id" . 1

      },

      "nama" . "_id_"

   },

   {

      "v" . 2,

      "kunci" . {

         "nama" . 1,

         "usia" . 1

      },

      "nama" . "nama_1_umur_1"

   },

   {

      "v" . 2,

      "kunci" . {

         "nama" . 1

      },

      "nama" . "nama_1"

   }

]

Kami juga menganggap indeks awalan paling kiri sebagai duplikat

Untuk memanfaatkan indeks majemuk MongoDB tidak perlu menggunakan semua bidang indeks itu, awalan paling kiri sudah cukup. Misalnya indeks pada (A,B,C) dapat digunakan untuk memenuhi kombinasi (A), (A,B), (A,B,C) tetapi tidak (B) atau (B,C). Akibatnya, jika saya memiliki dua indeks berbeda, satu di (A, B, C) dan satu lagi di (A, B), yang kedua adalah duplikat karena yang pertama dapat digunakan dengan cara yang sama untuk menyelesaikan kueri dengan

Kemudian, temukan semua indeks duplikat dan jatuhkan karena tidak berguna. Berhati-hatilah dan periksa apakah aplikasi Anda tidak menggunakan petunjuk () pada indeks yang akan Anda jatuhkan

Untuk menghindari pemeriksaan manual semua koleksi untuk menemukan duplikatnya, saya berikan di sini kode javascript untuk itu

Kerang

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

var ldb = db. adminCommand( { daftarDatabase. 1 } );

 

untuk ( i = 0; i < ldb.databases. panjang; i ++ ) {

 

   jika ( ldb. database[i]. nama . = 'admin' && ldb. database[i]. nama. = 'konfigurasi' && ldb. database[i]. nama. = 'lokal') {

 

print('DATABASE',ldb. database[i]. nama);

      cetak("+++++++++++++++)

 

      var db = db.getSiblingDB(ldb. database[i]. nama);

      var cpd = db.getCollectionNames();

 

      untuk ( j = 0; j < cpd.length; j ++ ) {

 

         jika ( cpd[j] ! = 'sistem. profile' ) {

 

            var indeks = JSON.parse(JSON. merangkai(db. runCommand( { indeksdaftar. cpd[j] } . kursor ).cursor. gelombang pertama));

            cetak("KUMPULKAN. " + cpd[j]);

 

            untuk ( k = 0; k < indexes.length; k ++ ) {

 

               indeks[k] = (((JSON.stringify(indeks[k . kunci.key)). ganti("{","")).replace("}","")).replace( / , / g ,"_");

 

            }

 

            var ditemukan = salah;

 

            untuk ( k1 = 0; k1 < indexes.length; k1 ++ ) {

 

               untuk ( k2 = 0; k2 < indexes.length; k2 ++ ) {

 

                   jika ( k1 . = k2 ) {

 

                     if (indeks[k1].startsWith(indeks[k2],0)) {

 

                       cetak("{ " + indexes[k2]+" } is the left prefix of { "+indexes[k1]+" } and should be dropped");

 

                        ditemukan = benar;

 

                     }

                  }

               }

            }

 

            jika (. ditemukan) {

 

               cetak("tidak ada indeks duplikat yang ditemukan");

 

            }

 

            cetak("\n");

 

         }

      }

 

      cetak("\n");

   }

}

Catatan. skrip ini hanyalah pengujian awal dan dapat ditingkatkan, tetapi seharusnya berfungsi dalam banyak kasus

Temukan Indeks yang Tidak Digunakan

MongoDB memelihara statistik internal tentang penggunaan indeks. Setiap kali indeks digunakan untuk menyelesaikan kueri, penghitung tertentu adalah kenaikan. Setelah menjalankan MongoDB untuk waktu yang cukup lama – berhari-hari atau berminggu-minggu – statistiknya dapat diandalkan dan kami dapat mengetahui indeks mana yang telah digunakan atau tidak

Untuk melihat statistik indeks, MongoDB menyediakan tahapan dalam pipa agregasi. $indexStats

Di sini Anda dapat melihat contohnya

Kerang

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

rs_test. UTAMA> db. restoran. agregat([ { $ . : {} } ]) . cantik.pretty()

{

   "nama" . "borough_1",

   "kunci" . {

      "wilayah" . 1

   },

   "host" . "ip-172-30-2-12. 27017",

   "mengakses" . {

      "ops" . NumberLong(312),

      "sejak" . Tanggal ISO("2021-03-17T13. 48. 51. 305Z")

   },

   "spek" . {

      "v" . 2,

      "kunci" . {

         "wilayah" . 1

      },

      "nama" . "borough_1"

   }

}

{

   "nama" . "_id_",

   "kunci" . {

      "_id" . 1

   },

   "host" . "ip-172-30-2-12. 27017",

   "mengakses" . {

      "ops" . NumberLong(12),

      "sejak" . Tanggal ISO("2021-03-17T13. 48. 51. 305Z")

   },

   "spek" . {

      "v" . 2,

      "kunci" . {

         "_id" . 1

      },

      "nama" . "_id_"

   }

}

{

   "nama" . "cuisine_1_borough_1",

   "kunci" . {

      "masakan" . 1,

      "wilayah" . 1

   },

   "host" . "ip-172-30-2-12. 27017",

   "mengakses" . {

      "ops" . NumberLong(0),

      "sejak" . Tanggal ISO("2021-03-17T13. 48. 51. 305Z")

   },

   "spek" . {

      "v" . 2,

      "kunci" . {

         "masakan" . 1,

         "wilayah" . 1

      },

      "nama" . "cuisine_1_borough_1"

   }

}

Akses. ops adalah berapa kali indeks telah digunakan. Dalam contoh Anda dapat melihat { borough. 1 } telah digunakan 312 kali, indeks { _id } 12 kali, dan indeks { masakan. 1, kelurahan. 10 Kali. Yang terakhir bisa dijatuhkan

Jika database berjalan lama dengan jutaan kueri dieksekusi dan jika indeks tidak digunakan, kemungkinan besar itu tidak akan digunakan bahkan di masa mendatang

Maka Anda harus mempertimbangkan untuk menghapus indeks yang tidak digunakan untuk meningkatkan penulisan, mengurangi tekanan cache, dan juga menghemat ruang disk

Dengan menggunakan skrip berikut, Anda dapat mengetahui statistik indeks untuk semua koleksi

Kerang

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

var ldb = db. adminCommand( { daftarDatabase. 1 } );

 

   untuk (i = 0; i<ldb.databases. panjang; i ++ ) {

 

      cetak('DATABASE ',ldb.databases[i]. nama);

 

      jika ( ldb. database[i]. nama . = 'admin' && ldb. database[i]. nama. = 'konfigurasi' && ldb. database[i]. nama. = 'lokal' ) {

 

var db = db. getSiblingDB(ldb. database[i]. nama);

      var cpd = db.getCollectionNames();

 

      untuk (j = 0; j<cpd.length; j ++ ) {

 

         jika ( cpd[j] ! = 'sistem. profile' ) {

 

            cetak(cpd[j]);

 

            var pui = db.runCommand({ agregat . cpd[j] , . pipeline : [{$indexStats. {}}], . cursor: { batchSize. 100 } });

            printjson(pui);

 

         }

      }

 

      cetak('\n\n');

   }

}

Cari indeks yang memiliki "ops". AngkaPanjang(0)

Kesimpulan

Membuat indeks untuk menyelesaikan kueri adalah kebiasaan yang baik, tetapi berhati-hatilah untuk tidak menyalahgunakan pengindeksan. Pengindeksan yang berlebihan dapat menyebabkan penulisan yang lebih lambat, tekanan berlebihan pada cache memori, dan lebih banyak penggusuran

Anda harus mempertimbangkan mempertahankan indeks Anda dari waktu ke waktu membuang semua duplikat dan indeks yang tidak terpakai. Skrip yang disediakan dalam artikel ini dapat membantu analisis indeks Anda

Distribusi Percona untuk MongoDB adalah alternatif basis data MongoDB yang tersedia secara gratis, memberi Anda satu solusi yang menggabungkan komponen perusahaan terbaik dan terpenting dari komunitas sumber terbuka, dirancang dan diuji untuk bekerja sama

Bagaimana cara mengurangi ukuran indeks di MongoDB?

Jika Anda menjalankan MongoDB 2. 0+, Anda dapat menjalankan perintah kompak untuk mendefrag koleksi Anda dan membangun kembali indeks. Perintah kompak mengunci database jadi pastikan Anda tahu di mana Anda menjalankannya sebelumnya

Bagaimana cara mengurangi ukuran indeks saya?

Untuk memperkecil ukuran, coba lakukan rekondisi indeks dengan perintah ubah indeks .

Berapa ukuran indeks maksimum di MongoDB?

Jangkauan Maksimum . Panjang nama indeks tidak boleh lebih dari 125 karakter. Indeks majemuk dapat memiliki maksimum 31 bidang yang diindeks. A collection cannot have more than 64 indexes. The length of the index name cannot be longer than 125 characters. A compound index can have maximum 31 fields indexed.

Berapa ukuran maksimum batas kunci indeks?

Ukuran maksimum kunci indeks adalah 900 byte .