Sepertinya Anda lebih mementingkan performa.
Beberapa orang telah menyarankan untuk membagi menjadi 3 tabel (tabel kategori ditambah tabel referensi silang sederhana atau cara yang lebih canggih untuk memodelkan hierarki pohon, seperti kumpulan bersarang atau jalur terwujud), yang merupakan hal pertama yang saya pikirkan ketika saya membaca pertanyaan Anda .
Dengan indeks, pendekatan yang sepenuhnya dinormalisasi seperti itu (yang menambahkan dua GABUNG) masih akan memiliki kinerja baca yang "cukup bagus". Satu masalah adalah bahwa INSERT atau UPDATE ke acara sekarang juga dapat menyertakan satu atau lebih INSERT/UPDATE/DELETE ke tabel referensi silang, yang pada MyISAM berarti tabel referensi silang dikunci dan pada InnoDB berarti baris dikunci, jadi jika database Anda sibuk dengan sejumlah besar penulisan, Anda akan memiliki masalah pertentangan yang lebih besar daripada jika hanya baris peristiwa yang dikunci.
Secara pribadi, saya akan mencoba pendekatan yang sepenuhnya dinormalisasi ini sebelum mengoptimalkan. Tapi, saya akan menganggap Anda tahu apa yang Anda lakukan, bahwa asumsi Anda benar (kategori tidak pernah berubah) dan Anda memiliki pola penggunaan (banyak penulisan) yang membutuhkan struktur datar yang kurang dinormalisasi. Itu benar-benar bagus dan merupakan bagian dari NoSQL.
SET vs. "banyak kolom"
Jadi, untuk pertanyaan Anda yang sebenarnya "SET vs. banyak kolom", saya dapat mengatakan bahwa saya telah bekerja dengan dua perusahaan dengan insinyur cerdas (yang produknya adalah aplikasi web CRM ... satu sebenarnya adalah manajemen acara), dan keduanya menggunakan pendekatan "banyak kolom" untuk kumpulan data statis semacam ini.
Saran saya adalah memikirkan semua kueri yang akan Anda lakukan di tabel ini (ditimbang berdasarkan frekuensinya) dan cara kerja indeks.
Pertama, dengan pendekatan "banyak kolom" Anda akan memerlukan indeks pada setiap kolom ini sehingga Anda dapat melakukan SELECT FROM events WHERE CategoryX = TRUE
. Dengan indeks, itu adalah kueri yang sangat cepat.
Dibandingkan dengan SET, Anda harus menggunakan bitwise AND (&), LIKE, atau FIND_IN_SET() untuk melakukan kueri ini. Itu berarti kueri tidak dapat menggunakan indeks dan harus melakukan pencarian linier dari semua baris (Anda dapat menggunakan EXPLAIN untuk memverifikasi ini). Permintaan lambat!
Itulah alasan utama SET adalah ide yang buruk -- indeksnya hanya berguna jika Anda memilih berdasarkan kelompok kategori yang tepat. SET berfungsi dengan baik jika Anda memilih kategori berdasarkan peristiwa, tetapi tidak sebaliknya.
Masalah utama dengan pendekatan "banyak kolom" yang kurang dinormalisasi (dibandingkan dengan yang dinormalisasi sepenuhnya) adalah bahwa ia tidak menskala. Jika Anda memiliki 5 kategori dan mereka tidak pernah berubah, baiklah, tetapi jika Anda memiliki 500 dan mengubahnya, itu masalah besar. Dalam skenario Anda, dengan sekitar 30 yang tidak pernah berubah, masalah utamanya adalah ada indeks di setiap kolom, jadi jika Anda sering menulis, kueri tersebut menjadi lebih lambat karena jumlah indeks yang harus diperbarui. Jika Anda memilih pendekatan ini, Anda mungkin ingin memeriksa log kueri lambat MySQL untuk memastikan tidak ada kueri yang lambat karena pertengkaran pada waktu sibuk.
Dalam kasus Anda, jika milik Anda adalah aplikasi web yang banyak membaca, saya pikir menggunakan pendekatan "banyak kolom" (seperti yang dilakukan kedua produk CRM, untuk alasan yang sama) mungkin masuk akal. Itu pasti lebih cepat dari SET untuk kueri SELECT itu.
TL;DR Jangan gunakan SET karena kueri "pilih acara berdasarkan kategori" akan lambat.