ऐसा लगता है कि आप मुख्य रूप से प्रदर्शन को लेकर चिंतित हैं।
कुछ लोगों ने 3 टेबलों में विभाजित करने का सुझाव दिया है (श्रेणी तालिका प्लस या तो साधारण क्रॉस-रेफरेंस टेबल या ट्री पदानुक्रम मॉडलिंग का एक अधिक परिष्कृत तरीका, जैसे नेस्टेड सेट या भौतिक पथ), जो मैंने आपके प्रश्न को पढ़ते समय सबसे पहले सोचा था। ।
इंडेक्स के साथ, इस तरह एक पूरी तरह से सामान्यीकृत दृष्टिकोण (जो दो जॉइन जोड़ता है) में अभी भी "बहुत अच्छा" पढ़ने का प्रदर्शन होगा। एक मुद्दा यह है कि किसी ईवेंट में एक INSERT या UPDATE अब क्रॉस-रेफरेंस टेबल में एक या एक से अधिक INSERT/UPDATE/DELETEs भी शामिल हो सकता है, जिसका मतलब है कि MyISAM पर क्रॉस-रेफरेंस टेबल लॉक है और InnoDB पर इसका मतलब है कि रो लॉक हैं, इसलिए यदि आपका डेटाबेस बड़ी संख्या में लिखने में व्यस्त है तो आपको केवल ईवेंट पंक्तियों को लॉक करने की तुलना में बड़ी विवाद समस्याएँ होने वाली हैं।
व्यक्तिगत रूप से, मैं अनुकूलन करने से पहले इस पूरी तरह से सामान्यीकृत दृष्टिकोण का प्रयास करूंगा। लेकिन, मैं मान लूंगा कि आप जानते हैं कि आप क्या कर रहे हैं, कि आपकी धारणाएं सही हैं (श्रेणियां कभी नहीं बदलती हैं) और आपके पास एक उपयोग पैटर्न (बहुत सारे लेखन) हैं जो कम-सामान्यीकृत, सपाट संरचना की मांग करते हैं। यह पूरी तरह से ठीक है और NoSQL किस बारे में है इसका हिस्सा है।
SET बनाम "बहुत सारे कॉलम"
इसलिए, आपके वास्तविक प्रश्न "सेट बनाम बहुत सारे कॉलम" के रूप में, मैं कह सकता हूं कि मैंने स्मार्ट इंजीनियरों के साथ दो कंपनियों के साथ काम किया है (जिनके उत्पाद सीआरएम वेब एप्लिकेशन थे ... एक वास्तव में इवेंट मैनेजमेंट था), और वे दोनों इस तरह के स्थिर सेट डेटा के लिए "बहुत सारे कॉलम" दृष्टिकोण का इस्तेमाल किया।
मेरी सलाह होगी कि आप इस टेबल पर किए जाने वाले सभी प्रश्नों के बारे में सोचें (उनकी आवृत्ति द्वारा भारित) और इंडेक्स कैसे काम करेंगे।
सबसे पहले, "बहुत सारे कॉलम" दृष्टिकोण के साथ आपको इनमें से प्रत्येक कॉलम पर इंडेक्स की आवश्यकता होगी ताकि आप SELECT FROM events WHERE CategoryX = TRUE
कर सकें . इंडेक्स के साथ, यह एक सुपर-फास्ट क्वेरी है।
SET के साथ बनाम, आपको इस क्वेरी को करने के लिए बिटवाइज़ AND (&), LIKE, या FIND_IN_SET() का उपयोग करना चाहिए। इसका मतलब है कि क्वेरी एक इंडेक्स का उपयोग नहीं कर सकती है और सभी पंक्तियों की एक रैखिक खोज करनी चाहिए (आप इसे सत्यापित करने के लिए EXPLAIN का उपयोग कर सकते हैं)। धीमी क्वेरी!
यही मुख्य कारण है कि एसईटी एक बुरा विचार है - इसकी अनुक्रमणिका केवल तभी उपयोगी होती है जब आप श्रेणियों के सटीक समूहों द्वारा चयन कर रहे हों। यदि आप ईवेंट के आधार पर श्रेणियों का चयन कर रहे हैं, लेकिन इसके विपरीत नहीं, तो SET बहुत अच्छा काम करता है।
कम सामान्यीकृत "बहुत सारे कॉलम" दृष्टिकोण (बनाम पूरी तरह से सामान्यीकृत) के साथ प्राथमिक समस्या यह है कि यह स्केल नहीं करता है। यदि आपके पास 5 श्रेणियां हैं और वे कभी नहीं बदलती हैं, तो ठीक है, लेकिन यदि आपके पास 500 हैं और आप उन्हें बदल रहे हैं, तो यह एक बड़ी समस्या है। आपके परिदृश्य में, लगभग 30 जो कभी नहीं बदलते हैं, प्राथमिक मुद्दा यह है कि प्रत्येक कॉलम पर एक इंडेक्स होता है, इसलिए यदि आप बार-बार लिख रहे हैं, तो इंडेक्स की संख्या को अपडेट करने के कारण वे क्वेरी धीमी हो जाती हैं। यदि आप इस दृष्टिकोण को चुनते हैं, तो आप यह सुनिश्चित करने के लिए MySQL धीमी क्वेरी लॉग की जांच कर सकते हैं कि दिन के व्यस्त समय में विवाद के कारण अधिक धीमी क्वेरी नहीं हैं।
आपके मामले में, यदि आपका एक सामान्य पठन-भारी वेब ऐप है, तो मुझे लगता है कि "बहुत सारे कॉलम" दृष्टिकोण के साथ जाना (जैसा कि दो सीआरएम उत्पादों ने उसी कारण से किया था) शायद समझदार है। यह निश्चित रूप से है उस SELECT क्वेरी के लिए SET से तेज़।
TL;DR SET का उपयोग न करें क्योंकि "श्रेणी के अनुसार ईवेंट चुनें" क्वेरी धीमी होगी।