SQL

2011-08-24 12 views
6

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

मान लें कि मेरे पास एक सारणी है जिसमें टेक्स्ट कॉलम "फल" है। उस कॉलम में केवल चार मानों में से एक दिखाई देता है: नाशपाती, ऐप्पल, केला, और स्ट्रॉबेरी। मेरे पास दस लाख पंक्तियां हैं।

उस डेटा को (औसतन) एक चौथाई मिलियन बार दोहराने के बजाय, यदि मैं इसे एक अन्य तालिका में निकालता हूं जिसमें फलों का स्तंभ होता है और केवल चार पंक्तियां होती हैं, और फिर मूल स्तंभ को एक विदेशी कुंजी बनाते हैं, तो क्या यह करता है स्थान सुरक्षित करें?

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

यदि मेरी पंक्ति मान छोटे फल नामों से अधिक लंबे हैं तो मुझे लगता है कि बचत/अनुकूलन भी बड़ा है।

उत्तर

4

विदेशी कुंजी संबंधों के दोनों किनारों पर फ़ील्ड के डेटा प्रकार समान होना चाहिए।

यदि अभिभावक तालिका का मुख्य क्षेत्र (0) varchar(20) है, तो निर्भर तालिका में विदेशी कुंजी फ़ील्ड भी varchar(20) होना चाहिए। जिसका मतलब है, हां, आपको प्रत्येक टेबल में दोहराए जाने वाले 'ऐप्पल' और 'नाशपाती' और 'केला' की एक्स मिलियन पंक्तियां होनी चाहिए, जिनमें फलों की मेज पर एक विदेशी कुंजी है।

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

बेशक, आपको दोनों सेटअप को बेंचमार्क करना चाहिए। ये अंगूठे के सामान्य नियम हैं, और आपकी विशिष्ट आवश्यकताएं/सेटअप वास्तव में स्ट्रिंग-ए-कुंजी संस्करण के साथ तेजी से काम कर सकते हैं।

+0

एक संदर्भ प्रकार परिवर्तनीय 3 जीएल जैसे सी # .NET के बारे में सोचें: इसका मान स्मृति में एक स्थान पर निकलता है लेकिन इसमें कई संदर्भ चर हो सकते हैं जो उस स्थान पर केवल पूर्णांक (या जो भी) पॉइंटर्स हैं। डीबीएमएस पर एक ही सिद्धांत लागू किया जा सकता है: तर्कसंगत रूप से एफके में दोनों टेबल फल को पाठ के रूप में स्टोर करते हैं लेकिन कवर के नीचे पाठ केवल एक बार संग्रहीत होता है और प्रत्येक तालिका भौतिक रूप से एक ही मूल्य पर केवल एक पूर्णांक (या जो भी) सूचक को संग्रहीत करती है। क्या MySQL ऐसा करता है? मुझे लगता है कि प्रश्नकर्ता क्या हो रहा है। – onedaywhen

+1

मैं प्रोग्रामिंग भाषा के विरुद्ध mysql के डेटा स्टोरेज प्रथाओं की तुलना नहीं करूंगा। यह केवल एक प्रति स्टोर करने के लिए समझ में आता है, लेकिन विदेशी कुंजी संदर्भ नहीं हैं। वे किसी अन्य फ़ील्ड की तरह एक फ़ील्ड हैं जो उस डेटा को शामिल करता है जो किसी अन्य तालिका में समकक्ष फ़ील्ड/डेटा से मेल खाता है। आखिरकार - एक बड़ी मेज पर एक विदेशी कुंजी छोड़ना लगभग तात्कालिक है। यदि यह एक संदर्भ था, तो डीबीएमएस को वास्तविक डेटा पर प्रतिलिपि बनाना होगा कि संदर्भ समाप्त हो गया है। –

5

यह सही है।

आप

table fruits 
id name 
1 Pear 
2 Apple 
3 Banana 
4 Strawberry 

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

2
इसके बजाय दोहराने की

कि डेटा (औसतन) एक चौथाई मिलियन बार प्रत्येक, अगर मैं इसे एक एक और तालिका एक फल स्तंभ और सिर्फ उन चार पंक्तियों है, और फिर मूल स्तंभ एक विदेशी बनाने में निकालने कुंजी, क्या यह अंतरिक्ष को बचाता है?

नहीं यदि "फल" "लुकअप" तालिका की प्राथमिक कुंजी है, तो यह "बड़ी" तालिका में विदेशी कुंजी भी होनी चाहिए।

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

1

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

2

सामान्यीकरण केवल अंतरिक्ष के बारे में नहीं है, यह अक्सर डेटा व्यवहार के बारे में अनावश्यकता और मॉडलिंग के बारे में होता है और परिवर्तन के लिए केवल एक पंक्ति को अपडेट करने के बारे में भी - और केवल न्यूनतम मात्रा में डेटा अपडेट करके ताले के दायरे को कम करता है।

0

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

1

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

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