2008-09-24 11 views
34

मैं इसे जिज्ञासा से बाहर पूछ रहा हूं। असल में मेरा सवाल यह है कि जब आपके पास एक डेटाबेस होता है जिसके लिए एक पंक्ति प्रविष्टि की आवश्यकता होती है जो झंडे की तरह काम करती है, तो सबसे अच्छा अभ्यास क्या है? इसका एक अच्छा उदाहरण स्टैक ओवरफ़्लो पर बैज, या बगजिला में ऑपरेटिंग सिस्टम फ़ील्ड होगा। झंडे का कोई सबसेट किसी दिए गए प्रविष्टि के लिए सेट किया जा सकता है।डेटाबेस पंक्तियों में ध्वज, सर्वोत्तम प्रथाओं

आमतौर पर, मैं सी और सी ++ काम करता हूं, इसलिए मेरी आंत प्रतिक्रिया बिट्स के सेट के रूप में एक हस्ताक्षरित पूर्णांक फ़ील्ड का उपयोग करना है जिसे फ़्लिप किया जा सकता है ... लेकिन मुझे पता है कि कई कारणों से यह एक अच्छा समाधान नहीं है। सबसे स्पष्ट रूप से स्केल-क्षमता है, मेरे पास कितने झंडे हो सकते हैं पर एक कठिन ऊपरी सीमा होगी।

मैं कुछ अन्य समाधानों के बारे में भी सोच सकता हूं जो बेहतर पैमाने पर हैं लेकिन प्रदर्शन के मुद्दे होंगे क्योंकि उन्हें सभी जानकारी प्राप्त करने के लिए कई चयनों की आवश्यकता होगी।

तो, ऐसा करने का "सही" तरीका क्या है?

उत्तर

26

यदि आपको वास्तव में झंडे के बंद सेट (उदा। स्टैक ओवरफ्लो बैज) से एक असंबद्ध चयन की आवश्यकता है, तो "संबंधपरक तरीका" झंडे की एक तालिका और एक अलग तालिका बनाने के लिए होगा जो उन झंडे को आपकी लक्षित इकाइयों से जोड़ता है। इस प्रकार, उपयोगकर्ता, झंडे और उपयोगकर्ता टोफ्लैग।

हालांकि, यदि अंतरिक्ष दक्षता गंभीर चिंता है और क्वेरी-क्षमता नहीं है, तो एक हस्ताक्षरित मुखौटा लगभग भी काम करेगा।

+11

बस हस्ताक्षरित मुखौटा पर एक चेतावनी। यदि आपको उन प्रश्नों पर लिखना है जो पंक्तियों पर फ़िल्टर करते हैं जहां एक विशिष्ट बिट सेट किया जाता है, तो पंक्तियों की संख्या बड़ी हो जाती है जब पंक्तियों की संख्या बड़ी हो जाती है क्योंकि तार्किक और/या संचालन जहां क्लॉज इंडेक्स को कुशलता से उपयोग नहीं कर सकते हैं। – JohnFx

4

कई मामलों के लिए, यह कई चीजों पर निर्भर करता है - जैसे कि आपके डेटाबेस बैकएंड। यदि आप MySQL का उपयोग कर रहे हैं, उदाहरण के लिए, SET datatype वही है जो आप चाहते हैं।

असल में, यह केवल एक बिटमास्क है, प्रत्येक बिट को आवंटित मानों के साथ। MySQL 64-बिट मानों का समर्थन करता है (जिसका अर्थ है 64 अलग-अलग टॉगल)। यदि आपको केवल 8 की आवश्यकता है, तो यह केवल प्रति पंक्ति एक बाइट लेता है, जो कि बहुत ही बढ़िया बचत है।

यदि आपके पास ईमानदारी से एक ही फ़ील्ड में 64 से अधिक मान हैं, तो आपका क्षेत्र अधिक जटिल हो सकता है। आप फिर बीएलओबी डेटाटाइप में विस्तार करना चाहते हैं, जो बिट्स का सिर्फ एक कच्चा सेट है जिसे MySQL की कोई अंतर्निहित समझ नहीं है। इसका उपयोग करके, आप बिट फ़ील्ड की मनमानी संख्या बना सकते हैं कि MySQL बाइनरी, हेक्स, या दशमलव मानों के रूप में इलाज करने में प्रसन्न है, हालांकि आपको इसकी आवश्यकता है। यदि आपको 64 से अधिक विकल्पों की आवश्यकता है, तो अपने आवेदन के लिए उपयुक्त फ़ील्ड बनाएं। नकारात्मकता यह है कि क्षेत्र को मानव पठनीय बनाना मुश्किल है। BIT datatype भी 64 तक सीमित है।

+0

मैं नहीं करूँगा, लेकिन यह बिट मास्क समाधान का एक अच्छा कार्यान्वयन है। स्वीकृत उत्तर का –

28

आम तौर पर, मैं बिटमैस्क फ़ील्ड से बचता हूं। उन्हें भविष्य में पढ़ना मुश्किल होता है और उन्हें समझने के लिए डेटा के बहुत अधिक गहन ज्ञान की आवश्यकता होती है।

संबंधपरक समाधान पहले प्रस्तावित किया गया है। उदाहरण आप उल्लिखित देखते हुए, मैं कुछ इस तरह (SQL सर्वर में) बनाने होगा:


CREATE TABLE Users (
    UserId INT IDENTITY(1, 1) PRIMARY KEY, 
    FirstName VARCHAR(50), 
    LastName VARCHAR(50), 
    EmailAddress VARCHAR(255) 
); 

CREATE TABLE Badges (
    BadgeId INT IDENTITY(1, 1) PRIMARY KEY, 
    [Name] VARCHAR(50), 
    [Description] VARCHAR(255) 
); 

CREATE TABLE UserBadges (
    UserId INT REFERENCES Users(UserId), 
    BadgeId INT REFERENCES Badges(BadgeId) 
); 
+1

अच्छा उदाहरण, धन्यवाद। –

1

अगर कोई बस कुछ ही झंडे की तुलना में अधिक है, या भविष्य में ऐसा होने की संभावना है, मैं एक अलग इस्तेमाल करेंगे झंडे की मेज और उनके बीच कई से अधिक टेबल।

यदि झंडे का एक मुट्ठी भर है और मैं उन्हें कभी भी उपयोग में नहीं जा रहा हूं, तो मैं एक एसईटी() या बिटफील्ड या जो कुछ भी उपयोग करूंगा। वे पढ़ने के लिए आसान हैं और अधिक कॉम्पैक्ट हैं, लेकिन एक दर्द के लिए दर्द और कभी-कभी ओआरएम के साथ सिरदर्द का भी अधिक होता है।

यदि केवल कुछ झंडे हैं - और केवल कुछ झंडे होने के लिए जा रहे हैं - तो मैं बस कुछ बिट/बूलेन/आदि कॉलम बनाउंगा।

2

यदि झंडे के बहुत अलग अर्थ हैं और सीधे SQL क्वेरी या दृश्यों में उपयोग किया जाता है, तो BOOLEAN के कई कॉलम का उपयोग करना एक अच्छा विचार हो सकता है।

प्रत्येक ध्वज को एक अतिरिक्त कॉलम में रखें, क्योंकि आप उन्हें अलग से पढ़ और संशोधित करेंगे। ,

CREATE TABLE ... (
    warning_foo BOOLEAN, 
    warning_bar BOOLEAN, 
    warning_... 
    error_foo BOOLEAN, 
    error_bar BOOLEAN, 
    error_... BOOLEAN, 
    ... 
) 

हालांकि MySQL एक बूलियन प्रकार नहीं है आप: आप झंडे समूह चाहते हैं, सिर्फ अपने स्तंभ नाम एक आम उपसर्ग देते हैं, यानी बजाय:

CREATE TABLE ... (
    warnings INTEGER, 
    errors INTEGER, 
    ... 
) 

आप का उपयोग करना चाहिए उस उद्देश्य के लिए अर्ध मानक TINYINT (1) का उपयोग कर सकते हैं, और इसे केवल 0 या 1 पर सेट कर सकते हैं।

1

यदि आपका डेटाबेस इसका समर्थन करता है तो मैं एक बुलेन डेटाटाइप का उपयोग करने की अनुशंसा करता हूं।

अन्यथा, सबसे अच्छा तरीका NUMBER (1) या समकक्ष का उपयोग करना है, और कॉलम पर एक चेक बाधा डालें जो वैध मानों को सीमित करता है (0,1) और शायद यदि आपको इसकी आवश्यकता हो तो न्यूल। यदि कोई अंतर्निहित प्रकार नहीं है, तो एक संख्या का उपयोग करके एक अस्पष्ट कॉलम का उपयोग करके कम अस्पष्ट है। (सत्य के लिए मूल्य क्या है? "टी" या "वाई" या "टी")

इस बारे में अच्छी बात यह है कि आप सत्य पंक्तियों की संख्या को गिनने के लिए SUM() का उपयोग कर सकते हैं।

SELECT COUNT(1), SUM(ActiveFlag) 
FROM myusers; 
3

एक बहुत संबंधपरक दृष्टिकोण

सेट प्रकार के बिना डेटाबेस के लिए, आप संस्थाओं जिसके लिए प्रत्येक ध्वज सेट है के सेट का प्रतिनिधित्व करने के लिए एक नई तालिका खोल सके।

उदा। एक टेबल "स्टूडेंट्स" के लिए आपके पास टेबल "रजिस्टर्ड स्टूडेंट्स", "सिकस्ट्यूडेंट्स", ट्रबलस्मिथ स्टूडेंट आदि हो सकते हैं। प्रत्येक तालिका में केवल एक कॉलम होगा: student_id। यह वास्तव में बहुत तेज़ होगा यदि आप जानना चाहते हैं कि कौन से छात्र "पंजीकृत" या "बीमार" हैं, और प्रत्येक डीबीएमएस में उसी तरह काम करेंगे।

संबंधित मुद्दे