हमें NULLs की अनुमति क्यों नहीं देनी चाहिए?


125

मुझे डेटाबेस डिजाइन के बारे में यह एक लेख पढ़ना याद है और मुझे यह भी याद है कि आपके पास NOT NULL के क्षेत्र गुण होने चाहिए। मुझे याद नहीं कि ऐसा क्यों था।

मैं यह सोच सकता हूं कि एक एप्लिकेशन डेवलपर के रूप में, आपको NULL के लिए परीक्षण नहीं करना पड़ेगा और एक संभव डेटा डेटा मूल्य (उदाहरण के लिए, स्ट्रिंग के लिए एक रिक्त स्ट्रिंग)।

लेकिन आप दिनांक, डेटाटाइम और समय (SQL Server 2008) के मामले में क्या करते हैं? आपको कुछ ऐतिहासिक या नीचे-बाहर की तारीख का उपयोग करना होगा।

इस पर कोई विचार?



10
वास्तव में? RDBMS हमें NULL का उपयोग करने की अनुमति क्यों देता है, अगर हमें उनका उपयोग नहीं करना चाहिए? जब तक आप उनसे निपटना नहीं जानते, तब तक NULL में कुछ भी गलत नहीं है।
Fr0zenFyr

3
क्या यह बीआई डेटा मॉडलिंग था? आपको आम तौर पर वास्तव में तालिकाओं में नल की अनुमति नहीं देनी चाहिए ... अन्यथा, नल ठीक से उपयोग किए जाने पर आपके मित्र हैं। =)
सैम यि

2
@ Fr0zenFyr, सिर्फ इसलिए कि RDBMS हमें कुछ ऐसा करने की अनुमति देता है जो जरूरी नहीं कि ऐसा करना एक अच्छा विचार हो। कुछ भी नहीं हमें एक मेज में एक प्राथमिक कुंजी या एक अद्वितीय कुंजी घोषित करने के लिए मजबूर करता है, लेकिन कुछ अपवादों के साथ हम किसी भी तरह से करते हैं।
लेनार्ट

3
मुझे लगता है कि इस विषय का एक पूरा इलाज कोडड की मूल आवश्यकता के संदर्भ में करना होगा कि एक RDBMS के पास लापता डेटा के इलाज का एक व्यवस्थित तरीका होना चाहिए। वास्तविक दुनिया में, ऐसी परिस्थितियां हैं जहां डेटा के लिए एक स्थान बनाया जाता है, लेकिन इसमें डालने के लिए कोई डेटा नहीं है। डेटा आर्किटेक्ट को इस पर कुछ प्रतिक्रिया देनी होगी, चाहे वह डेटाबेस डिजाइन, एप्लिकेशन प्रोग्रामिंग या दोनों शामिल हो। SQL NULL इस आवश्यकता को पूरा करने में पूर्ण से कम है, लेकिन यह कुछ भी नहीं से बेहतर है।
वाल्टर मिटी

जवाबों:


229

मुझे लगता है कि सवाल खराब तरीके से व्यक्त किया गया है, क्योंकि शब्द का अर्थ है कि आपने पहले ही फैसला कर लिया है कि NULLs खराब हैं। शायद आपका मतलब था "क्या हमें NULLs की अनुमति देनी चाहिए?"

वैसे भी, यहाँ मेरा इस पर ध्यान है: मुझे लगता है कि NULLs एक अच्छी बात है। जब आप NULL को केवल इसलिए रोकना शुरू करते हैं क्योंकि "NULLs खराब हैं" या "NULLs कठिन हैं", तो आप डेटा बनाना शुरू करते हैं। उदाहरण के लिए, क्या होगा यदि आप मेरी जन्मतिथि नहीं जानते हैं? जब तक आप जानते हैं कि आप कॉलम में क्या डालने जा रहे हैं? यदि आप बहुत से विरोधी पूर्ण लोगों की तरह कुछ भी कर रहे हैं, तो आप 1900-01-01 दर्ज करने जा रहे हैं। अब मैं जराचिकित्सा वार्ड में रखा जा रहा हूँ और शायद मेरे स्थानीय समाचार स्टेशन से मुझे फोन मिल रहा है कि मुझे मेरे लंबे जीवन की बधाई दे, मेरे रहस्यों को इतनी लंबी ज़िंदगी जीने के लिए कहे, आदि।

यदि एक पंक्ति में प्रवेश किया जा सकता है जहां यह संभव है कि आप किसी कॉलम का मूल्य नहीं जानते हैं , तो मुझे लगता है कि NULL इस तथ्य का प्रतिनिधित्व करने के लिए कुछ मनमाना टोकन मूल्य चुनने की तुलना में बहुत अधिक समझ में आता है कि यह अज्ञात है - एक मूल्य जो अन्य करेगा पहले से ही पता है, रिवर्स इंजीनियर, या आसपास का पता लगाने के लिए इसका क्या मतलब है।

एक संतुलन है, हालांकि - आपके डेटा मॉडल में प्रत्येक स्तंभ अशक्त नहीं होना चाहिए। प्रपत्र पर अक्सर वैकल्पिक फ़ील्ड होते हैं, या जानकारी के टुकड़े जो अन्यथा पंक्ति बनाए जाने के समय एकत्र नहीं होते हैं। लेकिन इसका मतलब यह नहीं है कि आप सभी डेटा को पॉप्युलेट कर सकते हैं । :-)

इसके अलावा NULL का उपयोग करने की क्षमता वास्तविक जीवन में महत्वपूर्ण आवश्यकताओं द्वारा सीमित की जा सकती है। उदाहरण के लिए, चिकित्सा क्षेत्र में, यह जानना जीवन-मृत्यु का मामला हो सकता है कि कोई मूल्य अज्ञात क्यों है। क्या हृदय गति पूर्ण नहीं है क्योंकि एक नाड़ी नहीं थी, या क्योंकि हमने इसे अभी तक मापा नहीं है? ऐसे मामले में, क्या हम NULL को हृदय गति वाले कॉलम में रख सकते हैं, और NULL- कारण के साथ नोट या एक अलग कॉलम रख सकते हैं?

NULLs से डरो मत, लेकिन सीखने और तय करने के लिए तैयार रहें कि उन्हें कब और कहाँ इस्तेमाल किया जाना चाहिए, और कब और कहाँ नहीं करना चाहिए।


3
"इस तथ्य का प्रतिनिधित्व करने के लिए कुछ मनमाना टोकन मूल्य कि यह अज्ञात है" यह एक प्रहरी मूल्य के
अलेक्जेंडर

4
लेकिन आपको अलग-अलग तालिका बनाने से रोकता है birth_dateजहां आप जन्म तिथियां संग्रहीत करते हैं? यदि जन्म तिथि अज्ञात है, तो जन्म की तारीख डालें नहीं birth_date। नल आपदा हैं।
एल्डारॉला एग्रोवोव

6
@EldarAgalarov ट्रम्प तर्क की तरह लगता है ("आपदा" क्यों? कैसे? किसके लिए? आपकी राय है कि कुछ "आपदा" ऐसा नहीं है)। वैसे भी जन्म की तारीख सिर्फ एक उदाहरण है। यदि आपके पास ऐसे कर्मचारी या सदस्य या ग्राहक हैं, जिनके पास 15 संभावित अशक्त स्तंभ हैं, तो क्या आप 15 माध्यमिक तालिकाएँ बनाने जा रहे हैं? यदि आपके पास 50 है तो क्या होगा? क्या होगा अगर आपके DW तथ्य तालिका में 500 हैं? बड़ा बुरा डरावना NULLs अपने डेटाबेस से बाहर रखने के रखरखाव किसी भी "आपदा" आप में से ... डर है के रूप में 10x के रूप में बुरा हो जाता है
हारून बर्ट्रेंड

3
@AaronBertrand यदि आपकी तालिका में 15 संभावित अशक्त स्तंभ हैं, तो यह वास्तव में खराब है। लेकिन यह सवाल उठाएंगे।
कार्यक्रम

2
@Wildcard तो आपने लोगों को कभी भी 1900-01-01NULL डेट / टाइम वैल्यू से बचने के लिए स्टोर करते नहीं देखा है ? ठीक है फिर। इसके अलावा, NULL = अज्ञात और अज्ञात = गलत। मुझे यकीन नहीं है कि लोगों की तुलना में यह क्या समस्याएं पैदा कर सकता है, यह जानने के लिए पैदा नहीं हुआ है (जैसे कि वे एक जटिल आरडीबीएमएस में निहित बहुत सी चीजों को जानने से पैदा नहीं हुए हैं)। फिर, हाथ लहराते हुए और कहा "समस्या! आपदा!" ऐसा नहीं है।
हारून बर्ट्रेंड

57

स्थापित कारण हैं:

  • NULL कोई मान नहीं है, और इसलिए कोई आंतरिक डेटा प्रकार नहीं है। सभी स्थानों पर नल को विशेष हैंडलिंग की आवश्यकता होती है जब कोड जो अन्यथा वास्तविक प्रकारों पर निर्भर करता है, को बिना-टाइप किए हुए NULL भी प्राप्त हो सकता है।

  • NULL दो-मूल्य (परिचित ट्रू या गलत) लॉजिक को तोड़ता है, और तीन-मान वाले तर्क की आवश्यकता होती है। यह सही ढंग से लागू करने के लिए कहीं अधिक जटिल है, और निश्चित रूप से ज्यादातर डीबीए द्वारा और केवल सभी गैर-डीबीए के बारे में खराब समझा जाता है। परिणामस्वरूप, यह अनुप्रयोग में कई सूक्ष्म बगों को सकारात्मक रूप से आमंत्रित करता है

  • किसी भी विशिष्ट शून्य का अर्थ अर्थ आवेदन करने के लिए छोड़ दिया जाता है , वास्तविक मान के विपरीत है।

    "लागू नहीं" और "अज्ञात" और "प्रहरी" जैसे शब्दार्थ आम हैं, और अन्य भी हैं। वे अक्सर एक ही डेटाबेस के भीतर एक ही संबंध में भी उपयोग किए जाते हैं; और निस्संदेह अस्पष्ट और अविभाज्य और असंगत अर्थ हैं।

  • वे रिलेशनल डेटाबेस के लिए आवश्यक नहीं हैं , जैसा कि "बिना नल के गुम जानकारी को कैसे संभालना" में तर्क दिया गया था । आगे सामान्यीकरण NULLs की तालिका को हटाने की कोशिश करने के लिए एक स्पष्ट पहला कदम है।

इसका मतलब यह नहीं है कि NULL को कभी अनुमति नहीं दी जानी चाहिए। यह तर्क देता है कि जहाँ भी संभव हो वहां NULL को हटाने के कई अच्छे कारण हैं।

गौरतलब है कि यह बहुत कठिन प्रयास करने के लिए तर्क देता है - बेहतर स्कीमा डिज़ाइन, और बेहतर डेटाबेस इंजन, और यहां तक ​​कि बेहतर डेटाबेस भाषाओं के माध्यम से - NULL से बचने के लिए इसे संभव बनाने के लिए।

फैबियन पास्कल "नुल्स नुल्लिफ़ाइड" में कई तर्कों का जवाब देता है ।


3
आपका "नल के बिना गुम सूचना को कैसे संभालना है" के लिए आपका लिंक काफी अच्छी तरह से दिखाता है कि हम बिना नल के ऐसा क्यों नहीं कर सकते: कई सुझावों को प्रमुख RDBMSs पर तर्कसंगत तरीके से लागू करना असंभव होगा क्योंकि वे वर्तमान में खड़े हैं।
जैक डगलस

7
जैक: सही है, लेकिन "वर्तमान कार्यान्वयन यह नहीं कर सकता है" यथास्थिति के लिए एक तर्क नहीं है :-)
bignose

17
क्या इस तरह का कहना है कि हमें उड़ान नहीं भरनी चाहिए क्योंकि विमान सही नहीं हैं?
हारून बर्ट्रेंड

11
नहीं, यह कह रहा है कि विक्रेताओं को चालीस साल पहले वैध होने वाले नल के लिए बहाने बनाना बंद करना चाहिए, लेकिन लंबे समय से उनकी उचित अवधारण अवधि की रूपरेखा तैयार की गई है। I / O बार 80ms के परिमाण के क्रम में नहीं हैं। एकल सीपीयू चक्र अब माइक्रोसेकंड के परिमाण के क्रम में नहीं हैं। मेमोरी की सीमाएँ अब कुछ Megs के परिमाण के क्रम में नहीं हैं। चालीस साल पहले की तुलना में, नल के बिना काम करने के लिए आवश्यक हार्डवेयर की गति और क्षमता अब निषेधात्मक नहीं होने की लागत के साथ मौजूद हैं। वह कह रहा है कि यह आगे बढ़ने का समय है।
एरविन स्मूथ

2
"पूर्ण भ्रम" लिंक मृत है।
jpmc26

32

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

IIRC, Codd ने सुझाव दिया कि null का वर्तमान कार्यान्वयन (जिसका अर्थ है कि वर्तमान / गायब नहीं है) एक के बजाय दो नल मार्कर होने से सुधार किया जा सकता है, "वर्तमान नहीं बल्कि लागू" और "वर्तमान नहीं और लागू नहीं"। व्यक्तिगत रूप से इस संबंध में सुधार कैसे होगा, इसकी परिकल्पना नहीं की जा सकती।


2
मैं एक उपयोगकर्ता परिभाषित के विभिन्न प्रकार के सेट होने की सलाह देते हैं nullपी:, और उपयोगकर्ता-निर्धारित बहु-वैल्यूड लॉजिक उनके साथ जाने के लिए
जैक डगलस

13
वे एकमात्र विकल्प नहीं हैं। आप सामान्यीकरण विकल्प को बाहर करते हैं: स्तंभों के बजाय जिनका मान हो सकता है या नहीं हो सकता है, किसी अन्य तालिका का उपयोग करें, जिसमें पहली तालिका के लिए संबंधित पंक्ति हो सकती है या नहीं भी हो सकती है। किसी पंक्ति की उपस्थिति या अनुपस्थिति का अर्थ तालिकाओं के अर्थ में दर्ज किया गया है, और इसमें NULL या प्रहरी मूल्यों आदि का कोई विशेष आवरण नहीं है
bignose

7
NULL की उपस्थिति को विशेष-आवरण या प्रहरी मूल्यों की आवश्यकता नहीं है। वे सिर्फ इस बात के लक्षण हैं कि कुछ लोग NULLs से कैसे निपटते हैं।
हारून बर्ट्रेंड

यह ध्यान देने योग्य है कि '' PostgreSQL पर शून्य से अलग है (हालांकि ओरेकल नहीं) और इसलिए आपको दो गुना मार्कर देता है, और आप संख्यात्मक कॉलम के लिए 0 का उपयोग कर सकते हैं। यद्यपि 0 के साथ समस्या यह है कि यह विदेशी कुंजी के लिए काम नहीं करता है।
क्रिस ट्रैवर्स

13

मुझे यह कहते हुए शुरू करें कि मैं डीबीए नहीं हूं, मैं दिल से डेवलपर हूं और मैं अपनी जरूरतों के आधार पर अपने डेटाबेस को बनाए रखता हूं और अपडेट करता हूं। कहा जा रहा है, मैं कुछ कारणों के लिए एक ही सवाल था।

  1. अशक्त मूल्य विकास को अधिक कठिन और बग प्रवण बनाते हैं।
  2. अशक्त मूल्य प्रश्न, संग्रहीत कार्यविधियाँ बनाते हैं, और अधिक जटिल और बग प्रवण मानते हैं।
  3. अशक्त मान स्पेस लेते हैं (निश्चित कॉलम लंबाई पर आधारित बाइट्स या चर कॉलम लंबाई के लिए 2 बाइट्स)।
  4. अशक्त मूल्य अनुक्रमण और गणित को अक्सर प्रभावित कर सकते हैं।

मैं इंटरनेट पर प्रतिक्रियाओं, टिप्पणियों, लेखों और सलाह के भार के माध्यम से बहुत लंबा समय व्यतीत करता हूं। कहने की जरूरत नहीं है कि अधिकांश जानकारी @ AaronBertrand की प्रतिक्रिया के समान थी। यही कारण है कि मुझे इस प्रश्न का उत्तर देने की आवश्यकता महसूस हुई।

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

कहा जा रहा है कि एक ही कर्मचारी तालिका में सबसे अधिक संभावना किसी तरह के प्रमाणीकरण डेटा की होगी। यह एक उद्यम के माहौल में आम है कि कर्मचारियों को एचआर और लेखांकन के लिए डेटाबेस में सूचीबद्ध किया जाएगा, लेकिन हमेशा प्रमाणीकरण विवरण की आवश्यकता नहीं है या नहीं है। अधिकांश प्रतिक्रियाएं आपको विश्वास दिलाती हैं कि उन क्षेत्रों को शून्य करना ठीक है या कुछ मामलों में उनके लिए एक खाता बनाते हैं, लेकिन उन्हें कभी भी क्रेडेंशियल न भेजें। पूर्व आपकी विकास टीम को NULLs की जाँच करने के लिए कोड लिखने के लिए और तदनुसार उनके साथ व्यवहार करने का कारण बनेगा और बाद में एक बड़ा सुरक्षा जोखिम होता है! वे खाते जो सिस्टम में अभी तक उपयोग नहीं किए गए हैं, केवल एक हैकर के लिए संभव पहुंच बिंदुओं की संख्या में वृद्धि करते हैं, साथ ही वे उस चीज़ के लिए मूल्यवान डेटाबेस स्थान लेते हैं जो कभी उपयोग नहीं किया जाता है।

ऊपर दी गई जानकारी को देखते हुए, अशक्त डेटा से निपटने का सबसे अच्छा तरीका है कि अशक्त मूल्यों के लिए अनुमति दी जाए। यह दुखद है लेकिन सच है और आपके डेवलपर्स इसके लिए आपसे नफरत करेंगे। दूसरे प्रकार के अशक्त डेटा को संबंधित तालिका (IE: खाता, क्रेडेंशियल्स, आदि) में रखा जाना चाहिए और एक-से-एक संबंध होना चाहिए। यह किसी उपयोगकर्ता को तब तक क्रेडेंशियल के बिना मौजूद रहने की अनुमति देता है जब तक कि उनकी आवश्यकता न हो। यह अतिरिक्त सुरक्षा जोखिम, मूल्यवान डेटाबेस स्थान को हटा देता है, और एक बहुत क्लीनर डेटाबेस के लिए प्रदान करता है।

नीचे एक बहुत ही सरलीकृत तालिका संरचना है जो आवश्यक अशक्त स्तंभ और एक-से-एक संबंध दोनों दिखा रही है।

अज्ञात अशक्त और एक-से-एक संबंध

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


2
मैं इसे सिर्फ इसलिए बदल दूंगा कि TerminationDateकर्मचारी रिकॉर्ड में कोई नहीं है, लेकिन एक तालिका है TerminatedEmployeeजिसके लिए कर्मचारियों को आवेदन समाप्त होने पर (कॉपी नहीं) में स्थानांतरित कर दिया जाता है जब वे समाप्त हो जाते हैं। जाहिर है यह खाता तालिका के साथ अच्छी तरह से काम करता है क्योंकि तालिका में कोई लिंक नहीं किया जाएगा TerminatedEmployee। यदि आपको अभी भी फोन नंबरों की आवश्यकता है, तो मैं विदेशी कुंजियों को उलट दूंगा ताकि कर्मचारी और समाप्त कर्मचारी तालिकाओं के चारों ओर दूसरे तरीके के बजाय फोन नंबर की आईडी हो।
प्रोग्रामर

2
मैं सचमुच इस बारे में दिनों तक जा सकता था कि यह बुरा क्यों होगा। अनावश्यक टेबल, खराब एसक्यूएल प्रैक्टिस, जिससे आपके डेवलपर्स को कर्मचारी डेटा के लिए दो जगहों पर देखना होगा, रिपोर्टिंग के मुद्दे, एक कर्मचारी को सीधे यूआरआई के साथ मुद्दे जो मौजूद नहीं है (स्थानांतरित हो गया है), और सूची जारी होती है और इसपर। खेतों के लिए NULLS होना पूरी तरह से ठीक है, किसी दिन इसका मूल्य होगा, यह उन खेतों के लिए एक और कहानी है जो कभी भरते नहीं हैं और जिनका कभी उपयोग नहीं होता है। इस कार्य को करने के लिए कई संभावित समस्याएँ और वर्कअराउंड एक क्षेत्र पर NULL के लिए जाँच के छोटे मुद्दे के लायक नहीं होंगे।
निकोलस एगुइरे

1
मैं असहमत हूं। केवल निरर्थक बात यह है कि समाप्ति की तारीख के लिए अशक्त क्षेत्र जो कभी भी भरा नहीं जा सकता है। डेवलपर्स को केवल उन आंकड़ों के लिए उपयुक्त तालिका में देखना होगा जो वे चाहते हैं, और प्रदर्शन में सुधार कर सकते हैं। यदि किसी कारण से, आप समाप्त और गैर-समाप्त कर्मचारी दोनों चाहते हैं, तो इसका समाधान एक जुड़ाव द्वारा किया जाता है, लेकिन 90% आपका आवेदन शायद एक या दूसरे को चाहेगा। मुझे लगता है कि मेरे द्वारा निर्दिष्ट लेआउट बेहतर है क्योंकि किसी कर्मचारी पर समाप्ति की तारीख होना असंभव है और उसके लिए अभी भी एक खाता होना चाहिए।
प्रोग्रामर

2
मैंने निरर्थक डेटा नहीं कहा, मैंने निरर्थक तालिकाओं को कहा। साथ ही, कर्मचारी तालिकाओं में किसी भी परिवर्तन को समाप्त तालिकाओं के साथ छेड़छाड़ करना चाहिए; यह एप्लिकेशन को त्रुटि-रहित बनाता है और यह डेवलपर के कार्य को बहुत कठिन बना देता है। इसके अलावा, एक समाप्ति तिथि क्षेत्र लगभग सभी के लिए भर जाएगा। यह एक दूसरे समान तालिका संरचना बनाने और चारों ओर डेटा स्थानांतरित करने के लिए बेकार और समस्याग्रस्त है। यह सुनिश्चित करने के लिए कि टेबल डेटा को स्थानांतरित और साफ करने के लिए हर बार परीक्षण शामिल नहीं किया गया है। किसी तालिका से डेटा को निकालने के लिए बुरा व्यवहार है, भले ही इसे स्थानांतरित करने के लिए। यदि आप एक एकल क्षेत्र से बहुत चिंतित हैं ...
निकोलस एगुइरे

1
... कि लगभग हमेशा समय में भरा जाएगा फिर एक कर्मचारी के साथ 1to1 संबंध के साथ एक समाप्ति तालिका बनाएं। मैं एक डीबीए के रूप में और एक डेवलपर के रूप में पूरे दिन कई तरह के डेटाबेस के साथ काम करता हूं और मुझे खुशी है कि मैंने आपके द्वारा प्रस्तावित संरचना के साथ एक के बाद एक आना शुरू किया है। विशेष रूप से एक डेवलपर के दृष्टिकोण से, यह सब कुछ लिखने और त्रुटि की जांच करने के लिए एक दुःस्वप्न होगा क्योंकि आपको नहीं पता होगा कि यह किस तालिका से आ रहा था। जॉइन करते हुए भी, सॉफ्टवेयर में लौटाए गए डेटा में शून्य डेटा के साथ एक फ़ील्ड होगा जो आपको अभी भी परीक्षण करने की आवश्यकता होगी।
निकोलस एगुइरे

13

NULL भ्रामक डेवलपर्स के साथ सभी मुद्दों के अलावा, NULLs में एक और बहुत गंभीर खामी है: प्रदर्शन

NULL'able कॉलम प्रदर्शन के दृष्टिकोण से एक आपदा हैं। उदाहरण के लिए पूर्णांक अंकगणित पर विचार करें। बिना NULL के एक समझदार दुनिया में, SIMD निर्देशों का उपयोग करके डेटाबेस इंजन कोड में पूर्णांक अंकगणित को वेक्टर करना "आसान" है, जो कि CPU की प्रति पंक्ति 1 पंक्ति से भी तेज गति से किसी भी गणना का प्रदर्शन करता है। हालाँकि, जिस समय आप NULL का परिचय देते हैं, आपको NULL बनाने वाले सभी विशेष मामलों को संभालने की आवश्यकता होती है। आधुनिक सीपीयू निर्देश सेट (पढ़ें: x86 / x64 / ARM और GPU तर्क भी) बस इसे कुशलता से करने के लिए सुसज्जित नहीं हैं।

एक उदाहरण के रूप में विभाजन पर विचार करें। एक उच्च स्तर पर, यह वह तर्क है जिसकी आपको एक गैर शून्य पूर्णांक के साथ आवश्यकता है:

if (b == 0)
  do something when dividing by error
else
  return a / b

NULL के साथ, यह थोड़ा और मुश्किल हो जाता है। bआप के साथ मिलकर एक संकेतक की आवश्यकता होगी यदि bशून्य और इसी तरह के लिए a। चेक अब बन जाता है:

if (b_null_bit == NULL)
   return NULL
else if (b == 0) 
   do something when dividing by error
else if (a_null_bit == NULL)
   return NULL
else 
   return a / b

NULL अंकगणित एक आधुनिक सीपीयू पर चलने के लिए काफी धीमा है, नॉट अरिथमेटिक (लगभग 2-3x के फैक्टर द्वारा)।

जब आप SIMD की शुरुआत करते हैं तो यह खराब हो जाता है। SIMD के साथ, एक आधुनिक Intel CPU एक ही निर्देश में 4 x 32-बिट पूर्णांक विभाजन कर सकता है, जैसे:

x_vector = a_vector / b_vector
if (fetestexception(FE_DIVBYZERO))
   do something when dividing by zero
return x_vector;

अब, SIMD भूमि में NULL को संभालने के तरीके भी हैं, लेकिन इसके लिए अधिक वैक्टर और CPU रजिस्टरों का उपयोग करना और कुछ चालाक कार्य करना आवश्यक है। यहां तक ​​कि अच्छी चाल के साथ, 5-10 गुणा धीमी रेंज में NULL पूर्णांक अंकगणितीय ढोंगी के प्रदर्शन का दंड और भी तीव्र अभिव्यक्ति के लिए।

उपरोक्त के लिए कुछ ऐसा है जो समुच्चय के लिए और कुछ हद तक जुड़ता है।

दूसरे शब्दों में: SQL में NULL का अस्तित्व डेटाबेस सिद्धांत और आधुनिक कंप्यूटरों के वास्तविक डिजाइन के बीच एक बाधा है। एक बहुत अच्छा कारण है NULL डेवलपर्स को भ्रमित करना - क्योंकि एक पूर्णांक प्रोग्रामिंग भाषा में एक पूर्णांक NULL नहीं हो सकता है - यह सिर्फ कंप्यूटर काम नहीं करता है।


10

दिलचस्प सवाल।

मुझे लगता है कि यह सब एक अनुप्रयोग डेवलपर के रूप में हो सकता है, आपको NULL के लिए परीक्षण नहीं करना पड़ेगा और संभव डेटा मान (उदाहरण के लिए, स्ट्रिंग के लिए एक रिक्त स्ट्रिंग)।

यह उससे कहीं अधिक जटिल है। नल के कई अलग-अलग अर्थ हैं और कई स्तंभों में नल की अनुमति नहीं देने का एक बहुत महत्वपूर्ण कारण यह है कि जब स्तंभ यह शून्य होता है तो इसका मतलब एक और केवल एक ही चीज है (अर्थात यह बाहरी जुड़ाव में नहीं दिखा)। इसके अतिरिक्त यह आपको डेटा प्रविष्टि के न्यूनतम मानक निर्धारित करने की अनुमति देता है जो वास्तव में सहायक है।

लेकिन आप दिनांक, डेटाटाइम और समय (SQL Server 2008) के मामले में क्या करते हैं? आपको कुछ ऐतिहासिक या नीचे-बाहर की तारीख का उपयोग करना होगा।

यह ठीक से नल के साथ एक समस्या दिखाता है, जिसका अर्थ है कि एक तालिका में संग्रहीत मान या तो "यह मान लागू नहीं होता है" या "हम नहीं जानते।" स्ट्रिंग्स के साथ, एक खाली स्ट्रिंग "यह लागू नहीं होता है" के रूप में सेवा कर सकती है लेकिन तिथियों और समय के साथ, ऐसा कोई सम्मेलन नहीं है क्योंकि कोई मान्य मूल्य नहीं है जो पारंपरिक रूप से इसका मतलब है। आमतौर पर वहाँ आप NULLs का उपयोग करके अटक जाएंगे।

इसके आस-पास होने के तरीके (अधिक संबंध जोड़कर और जुड़कर) हैं, लेकिन उन सटीक अर्थ संबंधी स्पष्टता की समस्या है जो डेटाबेस में NULL को होती है। इन डेटाबेस के लिए मैं इस बारे में चिंता नहीं करेगा। वास्तव में इसके बारे में आप कुछ भी नहीं कर सकते हैं।

संपादित करें: एक क्षेत्र जहां NULLs अपरिहार्य हैं विदेशी कुंजियों में है। यहाँ वे आम तौर पर केवल एक ही अर्थ रखते हैं, बाहरी जुड़ाव अर्थ में अशक्त के समान। यह पाठ्यक्रम की समस्या का एक अपवाद है।


10

SQL Null पर विकिपीडिया के लेख में NULL मान के बारे में कुछ दिलचस्प टिप्पणियां हैं, और एक डेटाबेस-अज्ञेयवादी उत्तर के रूप में, जब तक आप अपने विशिष्ट RDBMS के लिए NULL मान रखने के संभावित प्रभावों के बारे में जानते हैं, वे आपके डिज़ाइन में स्वीकार्य हैं। यदि वे नहीं थे, तो आप कॉलम को अशक्त के रूप में निर्दिष्ट नहीं कर पाएंगे।

बस इस बात से अवगत रहें कि कैसे आपका आरडीबीएमएस उन्हें सेलेक्ट ऑपरेशन्स जैसे कि गणित और इंडेक्स में भी संभालता है।


-12

वाह, सही उत्तर "जब आपको प्रदर्शन करने की आवश्यकता न हो तो NULLs की अनुमति न दें क्योंकि वे प्रदर्शन को नीचा दिखा रहे हैं" किसी भी तरह से अंतिम मूल्यांकन किया गया उत्तर है। मैं इसे उभारूंगा और विस्तृत करूंगा। जब एक RDBMS गैर-विरल कॉलम के लिए NULLs की अनुमति देता है, तो उस कॉलम को एक बिटमैप में जोड़ा जाता है जो यह ट्रैक करता है कि क्या मूल्य प्रत्येक व्यक्तिगत पंक्ति के लिए NULL है। इसलिए तालिका में एक स्तंभ में NULL-क्षमता जोड़कर जहां सभी कॉलम NULLs की अनुमति नहीं देते हैं, आप तालिका को सहेजने के लिए आवश्यक संग्रहण स्थान बढ़ा रहे हैं। इसके अलावा, आपको बिटमैप को पढ़ने और लिखने के लिए RDBMS की आवश्यकता होती है, जो सभी कार्यों पर प्रदर्शन को कम करता है।

इसके अलावा, कई उदाहरणों में, NULLs 3NF को तोड़ने की अनुमति देगा। जबकि मैं अपने कई सहयोगियों की तरह 3NF के लिए एक स्टिकर नहीं हूं, निम्नलिखित परिदृश्य पर विचार करें:

व्यक्ति तालिका में एक स्तंभ है, जिसे DateOfDeath कहा जाता है, जो कि अशक्त है। यदि किसी व्यक्ति की मृत्यु हो गई है, तो यह उनके DateOfDeath के साथ भरा जाएगा, अन्यथा इसे NULL छोड़ दिया जाएगा। एक गैर-अशक्त सा स्तंभ भी है, जिसे IsAlive कहा जाता है। यदि व्यक्ति जीवित है तो यह कॉलम 1 पर सेट है, और यदि व्यक्ति मृत है। संग्रहीत प्रक्रियाओं के विशाल बहुमत ने IsAiveive कॉलम का उपयोग किया है, वे केवल तभी देखभाल करते हैं जब कोई व्यक्ति जीवित होता है, न कि उनका DateOfDeath।

हालाँकि, IsAlive कॉलम डेटाबेस के सामान्यीकरण को तोड़ देता है, क्योंकि यह DateOfDeath से पूरी तरह से व्युत्पन्न है। लेकिन चूंकि IsAlive SPs के बहुमत में हार्ड-वायर्ड है, इसलिए सीधा उपाय है कि DateOfDeath को गैर-अशक्त बना दिया जाए, और उस व्यक्ति के स्तंभ में एक डिफ़ॉल्ट मान असाइन किया जाए जो अभी भी जीवित है। कुछ SPs जो DateOfDeath का उपयोग करते हैं, फिर IsAlive कॉलम की जांच करने के लिए फिर से लिखा जा सकता है, और यदि व्यक्ति जीवित नहीं है, तो केवल DateOfDeath का सम्मान करें। फिर से, चूंकि अधिकांश SP केवल IsAlive (एक बिट) के बारे में परवाह करते हैं, न कि DateOfDeath (एक तारीख) का उपयोग करके इस पैटर्न का उपयोग काफी तेजी से होता है।

सभी स्कीमाओं में बिना NULLs वाले अशक्त स्तंभ खोजने के लिए एक उपयोगी T-SQL स्क्रिप्ट है:

select 'IF NOT EXISTS (SELECT 1 FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' WHERE ' + QUOTENAME(c.name) + ' IS NULL)
    AND (SELECT COUNT(*) FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ') > 1 PRINT ''' + s.name + '.' + t.name + '.' + REPLACE(c.name, '''', '''''') + ''''
    from sys.columns c
    inner join sys.tables t ON c.object_id = t.object_id
    inner join sys.schemas s ON s.schema_id = t.schema_id
    where c.is_nullable = 1 AND c.is_computed = 0
    order by s.name, t.name, c.name;

यदि आप इसे अपने उत्पादन डेटाबेस की एक प्रति पर चलाते हैं, तो आप उन स्तंभों को पा सकते हैं जिन्हें NULL को अनुमति देने के रूप में चिह्नित किया गया है, जिनका कोई NULLs अभ्यास में नहीं है। इनमें से अधिकांश को NULL के रूप में चिह्नित नहीं किया जा सकता है, जिससे प्रदर्शन में वृद्धि होती है और भंडारण स्थान कम होता है।

सभी तालिकाओं में सभी NULL को समाप्त करना संभव नहीं है और अभी भी एक साफ डिजाइन हो सकता है, लेकिन यथासंभव अधिक NULLs को समाप्त करने में काफी फायदा है। ऑप्टिमाइज़र इस जानकारी के साथ बहुत तेज़ी से काम करता है, और यदि आप एक तालिका में सभी NULL को समाप्त कर सकते हैं तो आप काफी मात्रा में भंडारण स्थान प्राप्त कर सकते हैं।

मुझे पता है कि प्रदर्शन कुछ ऐसा नहीं है जो डीबीए सोचता है कि सभी के बारे में बहुत कुछ है, लेकिन आप केवल एक सीमित मात्रा में मेमोरी और प्रोसेसर पावर को एक समाधान पर फेंक सकते हैं, कुछ बिंदु जो आप तार्किक और शारीरिक डिजाइन के बारे में सोचना शुरू करेंगे। ।

यह भी ध्यान दें कि यह केवल सच्चे RDBMSes के लिए है और मैं SQL सर्वर से अपने उत्तरों के तकनीकी हिस्से को आधार बना रहा हूं। Nulls के बिना अशक्त स्तंभों को खोजने के लिए सूचीबद्ध T-SQL भी SQL सर्वर से है।


1
टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
पॉल व्हाइट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.