Strategi ranged dan hashed pada Chapter sebelumnya hanyalah cara memotong; kualitas potongannya ditentukan oleh bahan bakunya: field yang kita angkat menjadi shard key. Dokumentasi resmi menyarikan evaluasi kandidat ke tiga kriteria — cardinality, frequency, dan monotonic changes — ditambah satu pertimbangan praktis: pola query. Kita bedah keempatnya di chapter ini, lengkap dengan latihan menghitung cardinality dan frequency dari data sungguhan di server latihan.

Tiga Kriteria Resmi #

Cardinality adalah jumlah nilai berbeda yang mungkin dimiliki field. Cardinality menentukan batas atas jumlah chunk — satu nilai unik hanya boleh hidup di satu chunk — sehingga field dengan cardinality rendah menutup ruang distribusi. Contoh klasik dari dokumentasi: field continent hanya punya tujuh nilai; cluster yang di-shard menurutnya efektifnya maksimal tujuh shard, karena shard kedelapan tidak akan pernah menerima chunk baru.

Frequency adalah sebaran kemunculan nilai. Cardinality tinggi tidak menolong bila sebagian besar document memuat nilai yang sama: chunk pemilik nilai dominan itu membengkak, tidak bisa dipecah (nilai tunggal tidak bisa dipotong), dan menjadi bottleneck baca-tulis. Gejala lanjutannya bernama jumbo chunk — dibedah di Chapter Troubleshooting Sharding.

Monotonic changes menilai apakah nilai field selalu bertambah (atau berkurang) seiring waktu. Contohnya ObjectId, timestamp, dan nomor urut. Pada ranged sharding, insert seperti ini selalu mendarat di chunk dengan batas atas MaxKey, menumpuk di satu shard — hotspot yang menghapus manfaat utama sharding. Obatnya satu: gunakan hashed sharding untuk key seperti ini.

Ketiganya bisa kita ukur dari data sendiri. Kita siapkan mini-lab berisi delapan peserta seminar dengan sebaran negara yang timpang:

js
db.peserta.insertMany([
  { userId: 1, negara: "ID", nama: "Budi" },
  { userId: 2, negara: "ID", nama: "Siti" },
  { userId: 3, negara: "ID", nama: "Dewi" },
  { userId: 4, negara: "ID", nama: "Rina" },
  { userId: 5, negara: "ID", nama: "Tono" },
  { userId: 6, negara: "MY", nama: "Farid" },
  { userId: 7, negara: "MY", nama: "Aisyah" },
  { userId: 8, negara: "SG", nama: "Wei" }
])

Output yang Dihasilkan:

text
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId('6ad3d8dd05c64281e229573c'),
    '1': ObjectId('6ad3d8dd05c64281e229573d'),
    '2': ObjectId('6ad3d8dd05c64281e229573e'),
    '3': ObjectId('6ad3d8dd05c64281e229573f'),
    '4': ObjectId('6ad3d8dd05c64281e2295740'),
    '5': ObjectId('6ad3d8dd05c64281e2295741'),
    '6': ObjectId('6ad3d8dd05c64281e2295742'),
    '7': ObjectId('6ad3d8dd05c64281e2295743')
  }
}

Pertanyaan pertama: bila negara dijadikan shard key, bagaimana sebaran beban per nilai? Aggregation sederhana menjawabnya:

js
db.peserta.aggregate([
  { $group: { _id: "$negara", jumlah: { $sum: 1 } } },
  { $sort: { jumlah: -1 } }
])

Output yang Dihasilkan:

text
[
  { _id: 'ID', jumlah: 5 },
  { _id: 'MY', jumlah: 2 },
  { _id: 'SG', jumlah: 1 }
]

Lima dari delapan document bernilai ID — chunk milik ID akan menampung 62,5% data. Inilah frequency yang timpang: cardinality tiga sudah rendah, dan diperparah sebaran yang tidak merata.

Pertanyaan kedua: bagaimana cardinality kedua kandidat dibandingkan? Kita hitung sekaligus:

js
db.peserta.aggregate([
  { $group: { _id: null, total: { $sum: 1 }, negaraUnik: { $addToSet: "$negara" }, userUnik: { $addToSet: "$userId" } } },
  { $project: { total: 1, negaraUnik: { $size: "$negaraUnik" }, userUnik: { $size: "$userUnik" } } }
])

Output yang Dihasilkan:

text
[ { _id: null, total: 8, negaraUnik: 3, userUnik: 8 } ]

Dari delapan document, negara hanya menyumbang tiga nilai unik sedangkan userId menyumbang delapan — cardinality userId tumbuh linear mengikuti jumlah peserta, cardinality negara mentok di jumlah negara. Kesimpulan mini-lab: userId jauh lebih layak menjadi shard key, dan negara paling cocok jadi prefiks compound key bila kita butuh pemisahan geografis.

Contoh Kunci yang Baik dan Buruk #

KandidatVerdictAlasan
{ userId: "hashed" }BaikCardinality tinggi, sebaran merata, aman untuk key yang naik terus
{ negara: 1, userId: 1 }BaikPrefiks negara memungkinkan zones geografis, userId menaikkan cardinality
{ email: 1 }Baik bila lazimUnik per pengguna; tepat bila aplikasi sering mencari berdasarkan email
{ createdAt: 1 } rangedBurukMonotonic — semua insert menumpuk di chunk MaxKey
{ status: 1 }BurukCardinality rendah (segelintir nilai) dan frequency timpang
_id ObjectId rangedBurukObjectId naik terus; pakai hashed bila ingin sharding menurut _id

Perhatikan pola compound { negara: 1, userId: 1 }: field pertama menjawab kebutuhan organisasi (zones per wilayah, dibahas di Chapter Zones), field kedua menjawab distribusi. Compound key dievaluasi berlapis — cardinality gabungan adalah perkalian ruang nilai kedua field.

Shard Key Harus Muncul di Query #

Kriteria terakhir bersifat praktis: query yang menyertakan shard key (atau prefiksnya, untuk compound key) bisa dirutekan mongos ke shard yang tepat; query tanpa shard key disiarkan ke semua shard. Karena itu, daftar query paling sering aplikasi kita adalah bahan baku pemilihan shard key — bukan sekadar struktur data. Pola perutean ini dibedah penuh di Chapter Query di Sharded Collections.

Rangkuman #

  • Cardinality menentukan batas jumlah chunk; frequency menentukan kemerataan beban; monotonic changes memicu hotspot pada ranged sharding.
  • Ketiganya terukur dari data sendiri — mini-lab aggregation di atas menunjukkan negara kalah jauh dari userId di kedua ukuran sekaligus.
  • Shard key yang baik menyertakan query-query tersering aplikasi agar tetap targeted.
  • Shard key sulit diganti (refineCollectionShardKey, reshardCollection) — desain sejak awal, jangan menunggu gejala muncul.

Setelah kunci ditetapkan, pertanyaan berikutnya adalah bagaimana datanya dipotong: seluk-beluk chunk menanti di chapter berikutnya.