Det låter som att du framför allt bryr dig om prestanda.
Ett par personer har föreslagit att dela upp i 3 tabeller (kategoritabell plus antingen enkel korsreferenstabell eller ett mer sofistikerat sätt att modellera trädhierarkin, som kapslad uppsättning eller materialiserad bana), vilket är det första jag tänkte när jag läste din fråga .
Med index kommer ett helt normaliserat tillvägagångssätt som det (som lägger till två JOINs) fortfarande att ha "ganska bra" läsprestanda. Ett problem är att en INSERT eller UPPDATERING till en händelse nu också kan inkludera en eller flera INSERT/UPDATE/DELETEs till korsreferenstabellen, vilket på MyISAM betyder att korsreferenstabellen är låst och på InnoDB betyder att raderna är låsta, så om din databas är upptagen med ett betydande antal skrivningar kommer du att få större konfliktproblem än om bara händelseraderna var låsta.
Personligen skulle jag prova detta helt normaliserade tillvägagångssätt innan jag optimerar. Men jag antar att du vet vad du gör, att dina antaganden är korrekta (kategorier ändras aldrig) och att du har ett användningsmönster (många skrivningar) som kräver en mindre normaliserad, platt struktur. Det är helt okej och är en del av vad NoSQL handlar om.
SET kontra "många kolumner"
Så när det gäller din faktiska fråga "SET vs. massor av kolumner", kan jag säga att jag har arbetat med två företag med smarta ingenjörer (vars produkter var CRM-webbapplikationer ... den ena var faktiskt händelsehantering), och de båda använde metoden "massor av kolumner" för denna typ av statisk datauppsättning.
Mitt råd skulle vara att tänka på alla frågor du kommer att göra i den här tabellen (viktade efter deras frekvens) och hur indexen skulle fungera.
Först, med metoden "massor av kolumner" kommer du att behöva index på var och en av dessa kolumner så att du kan göra SELECT FROM events WHERE CategoryX = TRUE
. Med indexen är det en supersnabb fråga.
I motsats till SET måste du använda bitvis AND (&), LIKE eller FIND_IN_SET() för att göra den här frågan. Det betyder att frågan inte kan använda ett index och måste göra en linjär sökning på alla rader (du kan använda EXPLAIN för att verifiera detta). Långsam fråga!
Det är huvudorsaken till att SET är en dålig idé - dess index är bara användbart om du väljer efter exakta grupper av kategorier. SET fungerar utmärkt om du skulle välja kategorier efter händelse, men inte tvärtom.
Det primära problemet med den mindre normaliserade "många kolumner"-metoden (mot fullt normaliserad) är att den inte skalas. Om du har 5 kategorier och de ändras aldrig, bra, men om du har 500 och ändrar dem är det ett stort problem. I ditt scenario, med cirka 30 som aldrig förändras, är det primära problemet att det finns ett index på varje kolumn, så om du skriver ofta blir dessa frågor långsammare på grund av antalet index som måste uppdateras. Om du väljer det här tillvägagångssättet kanske du vill kontrollera MySQL långsamma frågelogg för att se till att det inte finns extrema långsamma frågor på grund av konflikter vid hektiska tider på dagen.
I ditt fall, om din är en typisk lästung webbapp, tror jag att det förmodligen är vettigt att använda "många kolumner"-metoden (som de två CRM-produkterna gjorde, av samma anledning). Det är definitivt snabbare än SET för den SELECT-frågan.
TL;DR Använd inte SET eftersom "välj händelser efter kategori"-frågan blir långsam.