Buat dua indeks parsial :
CREATE UNIQUE INDEX favo_3col_uni_idx ON favorites (user_id, menu_id, recipe_id)
WHERE menu_id IS NOT NULL;
CREATE UNIQUE INDEX favo_2col_uni_idx ON favorites (user_id, recipe_id)
WHERE menu_id IS NULL;
Dengan cara ini, hanya ada satu kombinasi (user_id, recipe_id)
di mana menu_id IS NULL
, menerapkan batasan yang diinginkan secara efektif.
Kemungkinan kekurangan:
- Anda tidak dapat memiliki referensi kunci asing
(user_id, menu_id, recipe_id)
. (Tampaknya tidak mungkin Anda menginginkan referensi FK selebar tiga kolom - gunakan kolom PK saja!) - Anda tidak dapat mendasarkan
CLUSTER
pada indeks parsial. - Kueri tanpa
WHERE
yang cocok kondisi tidak dapat menggunakan indeks parsial.
Jika Anda membutuhkan lengkap indeks, Anda juga dapat membuang WHERE
kondisi dari favo_3col_uni_idx
dan persyaratan Anda masih diberlakukan.
Indeks, yang sekarang terdiri dari seluruh tabel, tumpang tindih dengan yang lain dan menjadi lebih besar. Bergantung pada kueri umum dan persentase NULL
nilai, ini mungkin berguna atau tidak. Dalam situasi ekstrim bahkan mungkin membantu untuk mempertahankan ketiga indeks (dua yang parsial dan total di atas).
Ini adalah solusi yang baik untuk satu kolom nullable , mungkin untuk dua. Tapi itu keluar dari tangan dengan cepat karena Anda memerlukan indeks parsial terpisah untuk setiap kombinasi kolom yang dapat dibatalkan, sehingga jumlahnya bertambah secara binomial. Untuk beberapa kolom yang dapat dibatalkan , lihat sebagai gantinya:
- Mengapa batasan UNIK saya tidak terpicu?
Selain:Saya menyarankan untuk tidak menggunakan pengidentifikasi huruf besar-kecil di PostgreSQL.