क्या हमेशा एक स्वत: पूर्णांक प्राथमिक कुंजी रखना अच्छा अभ्यास है?


191

मेरे डेटाबेस में, मैं अपने द्वारा idबनाई गई हर टेबल के नाम के साथ एक ऑटो-इन्क्रीमेंटिंग पूर्णांक प्राथमिक कुंजी रखने की आदत में पड़ जाता हूं, ताकि मुझे किसी विशेष पंक्ति के लिए एक अद्वितीय लुकअप मिल जाए।

क्या यह एक बुरा विचार है? क्या इस तरह से करने में कोई कमियां हैं? कभी कभी मैं जैसे कई सूचकांकों होगा id, profile_id, subscriptionsजहां idअद्वितीय पहचानकर्ता है, profile_idविदेशी के लिए लिंक idएक की Profileमेज, आदि

या ऐसे परिदृश्य हैं जहां आप इस तरह के क्षेत्र को जोड़ना नहीं चाहते हैं?


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

24
@ अरुकाज बिंदु यह है कि यह सिस्टम के बारे में कुछ जानकारी लीक करता है। उदाहरण के लिए, मान लें कि डेटाबेस में उपयोगकर्ता-लिखित पोस्ट हैं, जिनमें से प्रत्येक को क्रमिक आईडी मिलती है। मान लें कि आप चार पोस्ट बनाते हैं, जिनमें से प्रत्येक में एक आईडी मिलती है: 4am (20), 5am (25), 8pm (100), और 9pm (200) पर। आईडी देखकर, आप देख सकते हैं कि केवल 5 पोस्ट 4am और 5am के बीच जोड़े गए थे, जबकि 100 को 8pm और 9pm के बीच जोड़ा गया था। यदि आप सेवा हमले से इनकार करने के लिए समय लेने की कोशिश कर रहे थे, तो यह बहुमूल्य जानकारी हो सकती है।
जोशुआ टेलर

29
"जर्मन टैंक समस्या" के बारे में शिकायत करने वाले हर व्यक्ति के लिए .... यदि किसी को डेटा तक पहुंचने से रोकने वाली एकमात्र चीज़ है जो आपके URL की एक कुंजी नहीं है ... तो आपके पास GUID बनाम ऑटो INT की तुलना में बड़ी समस्याएं हैं।
मैथ्यू व्हिट

11
@ मैथव्हीट यह एक URL में मापदंडों को स्वैप करने के बारे में नहीं है। मान लीजिए आप एक साइट का उपयोग करते हैं और आप समय पर संपत्ति 100 बनाते हैं t, और समय पर संपत्ति 120 t + 60। यदि आप उन दोनों आईडी (100 और 120) को बिना पढ़े हुए रूप में देख सकते हैं, तो अब आप कुल संपत्ति का पता लगा सकते हैं, जो मौजूद हैं और साथ ही वे जिस दर पर बनाए गए हैं। यह सूचना रिसाव है। यह विशुद्ध रूप से काल्पनिक नहीं है।
क्रिस हेस

15
"क्या यह हमेशा के लिए अच्छा व्यवहार है ..." नहीं
ब्रायन_

जवाबों:


137

गारंटीकृत अद्वितीय पंक्ति पहचानकर्ता होना कभी भी बुरा विचार नहीं है। मुझे लगता है कि मुझे कभी नहीं कहना चाहिए - लेकिन आइए एक अच्छा विचार है।

सैद्धांतिक संभावित डाउनसाइड में एक अतिरिक्त अनुक्रमणिका को बनाए रखने के लिए और अतिरिक्त भंडारण स्थान का उपयोग किया जाता है। यह एक कारण के लिए पर्याप्त नहीं है मेरे लिए एक का उपयोग नहीं करने के लिए।


11
यही तो मैं करता हूं। ज्यादातर लोग या तो 'id' या 'tablename_id' (जैसे user_id) का उपयोग करते हैं। यदि स्तंभ की आवश्यकता है, तो तर्क आमतौर पर नहीं है, लेकिन इसे नाम देने का कौन सा तरीका है।
ग्रैंडमास्टरबी

102
व्यक्तिगत रूप से मुझे लगता है कि तालिका का नाम बाकी का मतलब होना चाहिए। TableName.idके रूप में विरोध किया गया है TableName.TableName_id, क्योंकि और क्या idहै? यदि मेरे पास तालिका में एक और आईडी फ़ील्ड है, तो मैं इसे तालिका के नाम के साथ उपसर्ग करूंगा यदि यह किसी अन्य तालिका की बात कर रहा हो
AJJ

10
@ArukaJ आपने उल्लेख किया आप SQLite का उपयोग कर रहे हैं। यह वास्तव में एक विशेष मामला है, क्योंकि यह हमेशा इस तरह के एक स्तंभ को 'हुड के नीचे' बनाता है। इसलिए आप किसी अतिरिक्त स्थान का उपयोग भी नहीं कर रहे हैं क्योंकि आपको एक चाहिए जो आप चाहते हैं या नहीं। इसके अलावा, SQLite की पंक्तिबद्ध हमेशा 64 बिट पूर्णांक होती है। यदि मेरी यह समझ सही है, यदि आप एक ऑटो-इन्क्रिमेंटिंग पंक्ति को परिभाषित करते हैं, तो यह आंतरिक पंक्ति के लिए एक अन्य नाम होगा। तो तुम हमेशा अच्छी तरह से यह कर सकता था! देखें sqlite.org/autoinc.html
GrandmasterB

9
एक अपवाद मैं सोच सकता हूं कि क्या आपके पास एक विशिष्ट पहचानकर्ता है जो किसी अन्य तरीके से उत्पन्न होता है, उस स्थिति में जो प्राथमिक कुंजी होना चाहिए और एक ऑटो-इंक्रीडिंग आईडी निरर्थक है।
हम्माज

4
@GrandmasterB: SQLite का वर्तमान संस्करण एक अनुकूलन के रूप में WITHOUT ROWIDतालिकाओं (एक स्पष्ट PRIMARY KEY) के साथ बनाने की अनुमति देता है । लेकिन अन्यथा, एक INTEGER PRIMARY KEYकॉलम उपद्रवी के लिए एक उपनाम है।
dan04

91

मैं पहले सभी जवाबों से असहमत हूं। कई कारण हैं कि सभी तालिकाओं में ऑटो वेतन वृद्धि क्षेत्र को जोड़ना एक बुरा विचार है।

यदि आपके पास एक मेज है जहां कोई स्पष्ट चाबियाँ नहीं हैं, तो एक ऑटो-इंक्रीमेंट फ़ील्ड एक अच्छा विचार है। सब के बाद, आप नहीं करना चाहते हैं select * from blog where body = '[10000 character string]'। आप बल्कि करेंगे select * from blog where id = 42। मेरा तर्क है कि इनमें से अधिकांश मामलों में, जो आप वास्तव में चाहते हैं वह एक विशिष्ट पहचानकर्ता है; अनुक्रमिक अद्वितीय पहचानकर्ता नहीं। आप शायद इसके बजाय एक सार्वभौमिक अद्वितीय पहचानकर्ता का उपयोग करना चाहते हैं।

यादृच्छिक अद्वितीय पहचानकर्ता ( uuidmysql में, postgres। newidMssql में) उत्पन्न करने के लिए अधिकांश डेटाबेस में कार्य हैं । ये आपको किसी भी समय, किसी भी नेटवर्क कनेक्शन के साथ, विभिन्न डेटाबेस पर, कई डेटाबेस में डेटा उत्पन्न करने की अनुमति देते हैं, और फिर भी शून्य संघर्ष के साथ डेटा को मर्ज करते हैं। यह आपको और अधिक आसानी से कई सर्वरों और यहां तक ​​कि डेटा केंद्रों को सेटअप करने की अनुमति देता है, उदाहरण के लिए, जैसे कि माइक्रोसेवा के साथ।

यह उन हमलावरों से भी बचता है जो यूआरएल के उन पन्नों का अनुमान लगाते हैं जिनकी उन्हें पहुंच नहीं होनी चाहिए। अगर वहाँ वहाँ एक https://example.com/user/1263शायद के https://example.com/user/1262रूप में अच्छी तरह से है। यह उपयोगकर्ता प्रोफाइल पेज में एक सुरक्षा शोषण के स्वचालन की अनुमति दे सकता है।

ऐसे कई मामले भी हैं जहां एक यूआईडी कॉलम बेकार या हानिकारक भी है। मान लीजिए कि आपके पास एक सामाजिक नेटवर्क है। एक usersटेबल और एक friendsटेबल है। दोस्तों की तालिका में दो उपयोगकर्ता कॉलम और एक ऑटो-इन्क्रीमेंट फ़ील्ड है। आप के 3साथ दोस्ती करना चाहते हैं 5, इसलिए आप 3,5डेटाबेस में डालें । डेटाबेस एक ऑटो-इंक्रीमेंट आईडी और स्टोर जोड़ता है 1,3,5। किसी तरह, उपयोगकर्ता 3"मित्र जोड़ें" पर फिर से क्लिक करता है। आप 3,5फिर से डेटाबेस में सम्मिलित करते हैं, डेटाबेस एक ऑटो-इंक्रीमेंट आईडी और आवेषण जोड़ता है 2,3,5। लेकिन अब 3और 5दो बार एक दूसरे के साथ दोस्त हैं! यह अंतरिक्ष की बर्बादी है, और यदि आप इसके बारे में सोचते हैं, तो ऑटो-वृद्धि कॉलम है। आपको यह देखने की जरूरत है कि क्या aऔर क्याbदोस्तों उन दो मानों के साथ पंक्ति के लिए चयन करना है। वे एक साथ, एक अद्वितीय पंक्ति पहचानकर्ता हैं। (आप शायद यकीन है कि बनाने के लिए कुछ तर्क बारे में क्या करना चाहते हैं हैं 3,5और 5,3deduplicated कर रहे हैं।)

अभी भी ऐसे मामले हैं जहां अनुक्रमिक आईडी उपयोगी हो सकती है, जैसे कि url-shortener बनाते समय, लेकिन ज्यादातर (और यहां तक ​​कि url shortener के साथ) एक यादृच्छिक रूप से निर्मित अद्वितीय आईडी वह है जिसे आप वास्तव में उपयोग करना चाहते हैं।

टीएल; डीआर: यदि आप पहले से ही प्रत्येक पंक्ति की पहचान करने का एक अनूठा तरीका नहीं रखते हैं, तो ऑटो-वेतन वृद्धि के बजाय यूयूआईडी का उपयोग करें।


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

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

11
एक और परिदृश्य जब यूयूआईडी बेहतर होते हैं: एक आदर्श पीयूटी ऑपरेशन लागू करना, ताकि आप डुप्लिकेट पंक्तियों को पेश किए बिना अनुरोधों को सुरक्षित रूप से पुन: प्रयास कर सकें।
yurez

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

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

60

ऑटोइंटरमेंटल कीज के ज्यादातर फायदे हैं।

लेकिन कुछ संभावित कमियां हो सकती हैं:

  • यदि आपके पास कोई व्यवसाय कुंजी है, तो आपको व्यावसायिक नियमों को लागू करने के लिए उस कॉलम (ओं) पर एक अद्वितीय सूचकांक भी जोड़ना होगा।
  • दो डेटाबेस के बीच डेटा ट्रांसफर करते समय, खासकर जब डेटा एक से अधिक टेबल (यानी मास्टर / डिटेल) में होता है, तो यह स्ट्रेट-फॉरवर्ड नहीं होता है, क्योंकि सीक्वेंस डेटाबेस के बीच सिंक नहीं होते हैं, और आपको पहली बार उपयोग करके एक समतुल्यता तालिका बनानी होगी मूल डेटाबेस से कौन सी आईडी टारगेट डेटाबेस में किस आईडी से मेल खाती है, यह जानने के लिए मैच के रूप में बिजनेस की। यद्यपि / से पृथक तालिकाओं में डेटा स्थानांतरित करते समय यह समस्या नहीं होनी चाहिए।
  • कई उद्यमों में तदर्थ, चित्रमय, बिंदु और क्लिक, ड्रैग-एंड-ड्रॉप रिपोर्टिंग उपकरण हैं। चूंकि ऑटोइंटरमेंटल आईडी निरर्थक हैं, इसलिए इस प्रकार के उपयोगकर्ताओं को "ऐप" के बाहर डेटा की समझ बनाने में मुश्किल होगी।
  • यदि आप गलती से व्यापार कुंजी को संशोधित करते हैं, तो संभावना है कि आप उस पंक्ति को कभी भी पुनर्प्राप्त नहीं करेंगे क्योंकि अब आपके पास मनुष्यों के लिए इसे पहचानने के लिए कुछ नहीं है। जिसके कारण एक बार बिटकॉइन प्लेटफॉर्म में खराबी आ गई थी
  • कुछ डिजाइनर दो तालिकाओं के बीच एक जुड़ने वाली तालिका में एक आईडी जोड़ते हैं, जब पीके को बस दो विदेशी आईडी से बना होना चाहिए। जाहिर है कि यदि ज्वाइन टेबल तीन या अधिक टेबल के बीच है, तो एक ऑटोइन्क्रिमेंटल आईडी समझ में आता है, लेकिन तब आपको एक अद्वितीय कुंजी जोड़ना होगा जब यह व्यावसायिक नियमों को लागू करने के लिए एफके के संयोजन पर लागू होता है।

यहाँ सरोगेट कुंजी के नुकसान पर एक विकिपीडिया लेख अनुभाग है


13
सरोगेट कुंजी पर mt.gox दोष को दोष देने के बजाय संदिग्ध लगता है। समस्या यह थी कि उन्होंने अपनी मिश्रित कुंजी में सभी क्षेत्रों को शामिल किया , यहां तक ​​कि उत्परिवर्तनीय / निंदनीय क्षेत्र भी।
कोडइन्चोस

6
ऑटो-इंक्रीमेंट कुंजी का उपयोग करने का एक "सामाजिक" नुकसान यह है कि कभी-कभी "व्यवसाय" मान लेता है कि कभी भी कोई अंतराल नहीं होना चाहिए और यह जानने की मांग होनी चाहिए कि एक असफल सम्मिलित होने पर होने वाली लापता पंक्तियों का क्या हुआ (लेनदेन रोलबैक)।
रिक राइकर

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

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

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

19

बस इसके विपरीत, नहीं, आपको हमेशा एक संख्यात्मक AutoInc PK रखने की आवश्यकता नहीं है।

यदि आप अपने डेटा का सावधानीपूर्वक विश्लेषण करते हैं तो आप अक्सर डेटा में प्राकृतिक कुंजियों की पहचान करते हैं। यह अक्सर ऐसा होता है जब डेटा का व्यवसाय के लिए आंतरिक अर्थ होता है। कभी-कभी पीके प्राचीन प्रणालियों से आर्टिफैक्ट होते हैं जो व्यापार उपयोगकर्ता अपने सिस्टम की विशेषताओं का वर्णन करने के लिए दूसरी भाषा के रूप में उपयोग करते हैं। मैंने उदाहरण के लिए बेड़े प्रबंधन प्रणाली में "वाहन" तालिका की प्राथमिक कुंजी के रूप में उपयोग किए जाने वाले वाहन VIN नंबर देखे हैं।

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

कभी-कभी ग्राहक सार्थक मूल्य जैसे पॉलिसी नंबर उत्पन्न करने के लिए आप AutoInc PK का उपयोग कर सकते हैं। कुछ समझदार और प्रमुख शून्य आदि के बारे में व्यावसायिक नियमों को लागू करने के लिए शुरुआत मूल्य निर्धारित करना। यह शायद "दोनों दुनिया का सबसे अच्छा" दृष्टिकोण है।

जब आपके पास मूल्यों की छोटी संख्या होती है जो अपेक्षाकृत स्थिर होती हैं, तो उन मूल्यों का उपयोग करें जो सिस्टम उपयोगकर्ता के लिए समझ में आते हैं। 1,2,3 का उपयोग क्यों करें जब आप L, C, H का उपयोग कर सकते हैं जहाँ L, H और C एक बीमा "पॉलिसी प्रकार" संदर्भ में जीवन, कार और घर का प्रतिनिधित्व करते हैं, या, VIN उदाहरण पर लौटते हैं, कैसे "का उपयोग करने के बारे में" "टोयोटा के लिए? सभी टॉयटाटा कारों में एक VIN होता है जो "TO" शुरू होता है यह उपयोगकर्ताओं के लिए याद रखने के लिए एक कम चीज है, इससे उनके लिए प्रोग्रामिंग और उपयोगकर्ता त्रुटियों को पेश करने की संभावना कम हो जाती है और प्रबंधन की रिपोर्टों में पूर्ण विवरण के लिए एक उपयोगी विवरण भी हो सकता है जो रिपोर्ट को सरल बनाता है। लिखने के लिए और शायद जल्दी उत्पन्न करने के लिए।

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

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

EDIT एक अन्य महत्वपूर्ण मामला है जहाँ आपको एक ऑटोजेनरेटेड पीके की आवश्यकता नहीं है टेबल का मामला है जो दो अन्य तालिकाओं के प्रतिच्छेदन का प्रतिनिधित्व करता है। कार सादृश्य के साथ रहने के लिए, एक कार में 0..n एक्सेसरीज़ है, प्रत्येक एक्सेसरी को कई कारों पर पाया जा सकता है। तो इसका प्रतिनिधित्व करने के लिए आप एक Car_Accessory तालिका बनाएं जिसमें कार और एक्सेसरी से PKs हों और लिंक DOS आदि के बारे में अन्य प्रासंगिक जानकारी।

इस टेबल पर आपको (आमतौर पर) जरूरत नहीं है, यह एक AutoInc PK है - यह केवल कार के माध्यम से एक्सेस किया जाएगा "मुझे बताएं कि इस कार पर क्या सामान हैं" या एक्सेसरी से "उन्हें यह बताएं कि कारों में यह एक्सेसरी क्या है"


4
> सभी टॉयटाटा कारों में एक VIN होता है, जो "TO" शुरू होता है, यह सच नहीं है। वे "जेटी" से शुरू करते हैं यदि जापान में बनाया गया है। अमेरिकी-निर्मित टॉयोटास में पूरी तरह से अलग VINs हैं en.wikibooks.org/wiki/…
मोंटी हार्डर

17
Don't create a second, meaningless primary key; it's wasteful and may cause errors.हालाँकि, यदि आप किसी रिकॉर्ड के लिए विशिष्टता स्थापित करते हैं, तो 6 कॉलम का एक संयोजन है, तो सभी 6 पर हर समय शामिल होना बहुत ही त्रुटि है। डेटा स्वाभाविक रूप से एक पीके है, लेकिन आप idउन 6 स्तंभों पर एक स्तंभ और एक अद्वितीय बाधा का उपयोग कर बेहतर हैं।
17

14
मैं इनमें से कुछ सुझावों को मानता हूं, यह मेरे लिए थोड़ा दूर की बात है। हां, व्यावहारिक होना ठीक है, लेकिन मैं यह नहीं गिन सकता कि कोई व्यक्ति अपने पहले जन्म के जीवन को कितनी बार शपथ लेता है कि डोमेन से बाहर कुछ विशेषता बाकी दिनों के लिए अद्वितीय रहेगी। खैर, आमतौर पर जो लाइव होने के बाद दूसरे सप्ताह तक अच्छी तरह से काम करता था, जब पहले डुप्लिकेट्स बदल जाते थे। ;) पीके के रूप में एक "विवरण" का उपयोग करना अभी बाहर है।
एनओई

2
@ मेरी, मेरी बुर, तुम सही हो। गिरने योग्य स्मृति, यह 20 साल है क्योंकि मैंने बेड़े प्रबंधन प्रणालियों को तैयार किया था। नहीं VIN प्राथमिक कुंजी नहीं थी :) मैंने एक AutoInc Asset_ID IIRC का उपयोग किया, जो कि कुछ ऐसी चीज़ की ओर ले जाता है जिसे मैं भूल गया था। टेबल्स जो कई-से-कई रिश्तों के लिए लिंकर्स हैं जहां आप लिंक करते हैं, कहते हैं, कार को एक्सेसरी (उदाहरण के लिए सनरूफ) कई कारों में कई सामान होते हैं, इसलिए आपको "Car_Accessory" तालिका की आवश्यकता होती है जिसमें Car_ID और Accessory -ID शामिल होते हैं, लेकिन वास्तव में Car_Accesory_ID की आवश्यकता नहीं होती है एक AutoInc पीके
mcottle

7
यह वास्तव में आश्चर्यजनक है कि कितने ट्रूली अपरिवर्तनीय "प्राकृतिक कुंजी" हैं। एसएसएन का? नहीं, वे बदल सकते हैं। यह दुर्लभ है, लेकिन ऐसा हो सकता है। उपयोगकर्ताओं के नाम? नहीं। अंततः किसी के पास बदलने के लिए एक वैध व्यावसायिक कारण होगा। VIN अक्सर एक पाठ्यपुस्तक उदाहरण है, लेकिन कई अन्य नहीं हैं। यहां तक ​​कि घर के पते भी बदल सकते हैं, सड़क के नामकरण में परिवर्तन कर सकते हैं।
एरिक फनकेनबस

12

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

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


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

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

1
ठीक है, मुझे लगता है कि मैंने प्राकृतिक आईडी की परिभाषा को गलत समझा है; मैंने सोचा था कि यह केवल व्यापार नियमों द्वारा परिभाषित एक आईडी थी, वास्तव में अपरिवर्तनीय होने की गारंटी है या नहीं।
13

10

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

हर नियम में एक अपवाद होता है, इसलिए आपको निर्यात / आयात के लिए उपयोग की जाने वाली तालिकाओं और इसी तरह के एक-तरफ़ा तालिकाओं या अस्थायी तालिकाओं पर पूर्णांक निरूपण आईडी की आवश्यकता नहीं हो सकती है। आप वितरित सिस्टम पर ID के बजाय GUID को भी प्राथमिकता देंगे।

यहां कई उत्तर बताते हैं कि मौजूदा अद्वितीय कुंजी को लिया जाना चाहिए। भले ही इसमें 150 अक्षर हों? मुझे ऐसा नहीं लगता।

अब मेरा मुख्य बिंदु:

ऐसा लगता है कि ऑटॉनेरिमेंट पूर्णांक आईडी के प्रतिद्वंद्वी 20 टेबल तक के छोटे डेटाबेस के बारे में बोल रहे हैं। वहां वे प्रत्येक टेबल पर अलग-अलग दृष्टिकोण रख सकते हैं।

लेकिन एक बार जब आपके पास 400+ तालिकाओं के साथ एक ईआरपी है, तो पूर्णांक आईडी कहीं भी (केवल ऊपर बताए गए मामलों को छोड़कर) पूर्णांक है। आप अन्य अद्वितीय क्षेत्रों पर भरोसा नहीं करते हैं, भले ही वे अद्वितीयता के लिए मौजूद हों और सुरक्षित हों।

  • आप सार्वभौमिक समय-बचत, प्रयास-बचत, आसानी से याद रखने वाले सम्मेलन से लाभान्वित होते हैं।
  • ज्यादातर मामलों में आप JOINटेबल की जांच करते हैं कि चाबियां क्या हैं।
  • आपके पास अपने पूर्णांक ऑटॉइन्मेंट कॉलम के साथ काम करने वाले सार्वभौमिक कोड रूटीन हो सकते हैं।
  • आप मौजूदा तालिकाओं की आईडी का संदर्भ देकर केवल नए तालिकाओं या उपयोगकर्ता प्लगइन्स के साथ अपने सिस्टम का विस्तार नहीं कर सकते। वे पहले से ही वहाँ हैं, उन्हें जोड़ने के लिए कोई लागत नहीं है।

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


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

8

यह शानदार डिजाइनों के लिए अच्छा अभ्यास नहीं है। यानी - जब जरूरत न हो तो ऑटो इन्क्रीमेंट इंट प्राइमरी की हमेशा करना अच्छा नहीं है।

आइए एक उदाहरण देखें जहां किसी की आवश्यकता नहीं है।

आपके पास लेखों के लिए एक तालिका है - इसमें एक प्राथमिक प्राथमिक कुंजी idऔर एक varchar स्तंभ है जिसका नाम है title

आपके पास लेख श्रेणियों से भरा एक टेबल भी है - idइंट प्राइमरी की, वर्चर name

लेख तालिका में एक पंक्ति में id5 की संख्या है, और title "मक्खन के साथ हंस कैसे खाना है"। आप उस लेख को अपनी श्रेणियाँ तालिका में निम्न पंक्तियों के साथ जोड़ना चाहते हैं: "फाउल" ( आईडी : 20), "गूज" ( आईडी : 12), "कुकिंग" ( आईडी : 2), "मक्खन" (आईडी: 9) ।

अब, आपके पास 2 टेबल हैं: लेख और श्रेणियां। आप दोनों के बीच संबंध कैसे बनाते हैं?

आपके पास 3 कॉलम वाली तालिका हो सकती है: id (प्राथमिक कुंजी), article_id (विदेशी कुंजी), category_id (विदेशी कुंजी)। लेकिन अब आपके पास कुछ ऐसा है:

| आईडी | a_id | c_id |
| 1 | 5 | 20 |
| 2 | 5 | 12 |
| 3 | 5 | 2 |

एक बेहतर समाधान के लिए एक प्राथमिक कुंजी है जो 2 कॉलम से बना है।

| a_id | c_id |
| 5 | 20 |
| 5 | 12 |
| 5 | 2 |

इसे करने से पूरा किया जा सकता है:

create table articles_categories (
  article_id bigint,
  category_id bigint,
  primary key (article_id, category_id)
) engine=InnoDB;

ऑटो इंक्रीमेंट पूर्णांक का उपयोग नहीं करने का एक और कारण यह है कि यदि आप अपनी प्राथमिक कुंजी के लिए यूयूआईडी का उपयोग कर रहे हैं।

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

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


7

या ऐसे परिदृश्य हैं जहां आप इस तरह के क्षेत्र को जोड़ना नहीं चाहते हैं?

ज़रूर।

सबसे पहले, ऐसे डेटाबेस हैं जिनके पास कोई संकेत नहीं है (जैसे, ओरेकल, जो निश्चित रूप से आसपास के सबसे छोटे दावों में से एक नहीं है)। यह एक पहला संकेत होना चाहिए जो हर किसी को पसंद नहीं है या उन्हें ज़रूरत नहीं है।

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


9
(ऐसा नहीं है कि एक Oracle उपयोगकर्ता इस सवाल को माफ़ कर देता है लेकिन) क्या Oracle उसी तरह अनुक्रम का उपयोग नहीं करता है जिस तरह से अन्य व्यक्ति Autoincrement / Identity का उपयोग करते हैं? कह रही है कि ओरेकल के पास ऑटोइन्क्रिमेंट डेटा प्रकार नहीं है वास्तव में सिर्फ एक अर्ध तर्क है?
17

खैर, यह सिर्फ एक छोटी सी बात थी; मुख्य भाग यह है कि एक रनिंग आईडी हर टेबल के लिए उपयुक्त नहीं है, इस प्रकार बस हर एक टेबल पर ऑटो-आईडी को थप्पड़ मारने की आदत हो सकती है।
19

कोई दो प्राथमिक कुंजी नहीं हैं, केवल एक प्राथमिक कुंजी है और बाकी सभी को उम्मीदवार कुंजी कहा जाता है यदि वे प्राथमिक कुंजी के रूप में भी सेवा कर सकते हैं ..
rahul tyagi

7

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

ऐसी कुछ स्थितियाँ हैं जिनके बारे में मैं सोच सकता हूँ कि आप उनका उपयोग कैसे करना चाहते हैं, जिनमें से अधिकांश परिदृश्यों के लिए उबलते हैं जहाँ DB के एक उदाहरण पर एक तालिका नए ID मानों के लिए आधिकारिक स्रोत नहीं हो सकती है:

  • जब वृद्धिशील आईडी एक संभावित हमलावर के लिए बहुत अधिक जानकारी होगी। "सार्वजनिक-सामना" डेटा सेवाओं के लिए एक पहचान स्तंभ का उपयोग आपको "जर्मन टैंक समस्या" के लिए असुरक्षित बनाता है; यदि रिकॉर्ड आईडी 10234 मौजूद है, तो इसका कारण यह है कि रिकॉर्ड 10233, 10232, आदि मौजूद हैं, कम से कम 10001 रिकॉर्ड करने के लिए वापस, और फिर रिकॉर्ड 1001, 101 और 1 के लिए जांचना आसान है, जहां आपके पहचान कॉलम की शुरुआत हुई। V4 GUIDs मुख्य रूप से रैंडम डेटा से बने होते हैं, इस वृद्धिशील व्यवहार को डिज़ाइन द्वारा तोड़ते हैं, ताकि सिर्फ इसलिए कि एक GUID मौजूद है, GUID के बाइट को बढ़ाकर या घटाकर बनाया गया एक GUID आवश्यक रूप से मौजूद नहीं है, हमलावर के लिए एक सेवा का उपयोग करने के लिए कठिन बना रहा है। डंप टूल के रूप में एकल-रिकॉर्ड पुनर्प्राप्ति के लिए। अन्य सुरक्षा उपाय हैं जो बेहतर तरीके से पहुंच को प्रतिबंधित कर सकते हैं, लेकिन यह मदद करता है।
  • एम में: एम क्रॉस-रेफरेंस टेबल। यह एक की तरह है, लेकिन मैंने इसे पहले भी देखा है। यदि आपके डेटाबेस में दो टेबलों के बीच कई-से-कई संबंध हैं, तो गो-टू सॉल्यूशन एक क्रॉस-रेफरेंस टेबल है जिसमें प्रत्येक टेबल के पीके को संदर्भित करने वाले विदेशी प्रमुख कॉलम हैं। इस तालिका का PK वास्तव में हमेशा दो विदेशी कुंजियों की एक यौगिक कुंजी होनी चाहिए, ताकि अंतर्निहित सूचकांक व्यवहार हो सके और संदर्भों की विशिष्टता सुनिश्चित हो सके।
  • जब आप इस मेज पर बल्क में डालने और हटाने की योजना बनाते हैं। संभवतः पहचान स्तंभों में सबसे बड़ा नुकसान अतिरिक्त घेरा है जिसे आपको किसी अन्य तालिका या क्वेरी से पंक्तियों को सम्मिलित करते समय गुजरना पड़ता है, जहां आप मूल तालिका के प्रमुख मूल्यों को बनाए रखना चाहते हैं। आपको "पहचान सम्मिलित करना" चालू करना होगा (हालाँकि यह आपके DBMS में किया गया है), फिर मैन्युअल रूप से सुनिश्चित करें कि आप जो कुंजी डाल रहे हैं वह अद्वितीय है, और फिर जब आप आयात के साथ हो जाते हैं तो आपको पहचान काउंटर सेट करना होगा तालिका का मेटाडेटा अधिकतम मान तक मौजूद है। यदि यह ऑपरेशन इस तालिका पर बहुत अधिक होता है, तो एक अलग पीके योजना पर विचार करें।
  • वितरित टेबल के लिए।आइडेंटिटी कॉलम एकल-उदाहरण डेटाबेस, फेलओवर जोड़े और अन्य परिदृश्यों के लिए बहुत अच्छा काम करते हैं, जहां एक डेटाबेस उदाहरण किसी भी समय पूरे डेटा स्कीमा पर एकमात्र प्राधिकरण है। हालाँकि, केवल इतना बड़ा है कि आप जा सकते हैं और अभी भी एक कंप्यूटर पर्याप्त तेजी से हो सकता है। प्रतिकृति या लेन-देन लॉग शिपिंग आपको अतिरिक्त रीड-ओनली प्रतियां प्राप्त कर सकते हैं, लेकिन उस समाधान के पैमाने पर भी एक सीमा है। जितनी जल्दी या बाद में आपको डेटा के आवेषण को संभालने और फिर एक-दूसरे के साथ सिंक्रनाइज़ करने के लिए दो या अधिक सर्वर इंस्टेंसेस की आवश्यकता होगी। जब वह स्थिति आती है, तो आप एक वृद्धिशील के बजाय एक GUID फ़ील्ड चाहते हैं, क्योंकि ज्यादातर DBMSes GUIDs के एक हिस्से का उपयोग करने के लिए पूर्व-कॉन्फ़िगर होते हैं जो वे एक उदाहरण-विशिष्ट पहचानकर्ता के रूप में उत्पन्न करते हैं, फिर बाकी पहचानकर्ता को अनियमित रूप से उत्पन्न करते हैं या वृद्धिशील रूप से। किसी भी स्थिति में,
  • जब आपको DB में कई तालिकाओं में विशिष्टता लागू करनी होगी।उदाहरण के लिए, अकाउंटिंग सिस्टम में सामान्य लेज़र को प्रबंधित करना, प्रत्येक क्रेडिट के लिए एक पंक्ति के साथ (हर खाते के डेबिट के लिए जो कभी भी हुआ है, इसलिए यह बहुत बड़ा हो जाता है) तालिकाओं के अनुक्रम के रूप में प्रत्येक एक कैलेंडर महीने का प्रतिनिधित्व करता है / साल। फिर रिपोर्टिंग के लिए उन्हें एक साथ हुक करने के लिए दृश्य बनाए जा सकते हैं। तार्किक रूप से, यह सभी एक बहुत बड़ी तालिका है, लेकिन इसे चॉप करने से डीबी के रखरखाव के काम आसान हो जाते हैं। हालाँकि, यह डुप्लिकेट कुंजियों के साथ समाप्त हुए बिना कई तालिकाओं में आवेषण का प्रबंधन करने की समस्या को प्रस्तुत करता है (आपको अगले महीने में लेन-देन शुरू करने की अनुमति देता है। फिर, पहचान पूर्णांक स्तंभों के बजाय GUIDs गो-टू सॉल्यूशन हैं, क्योंकि DBMS को वास्तव में अद्वितीय तरीके से उत्पन्न करने के लिए डिज़ाइन किया गया है,

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


1
ऐसे मामले हैं जिन्हें आपको अभी भी एम: एन तालिकाओं (स्तंभों का उपयोग करके ID, ID_M, ID_N) की आवश्यकता हो सकती है क्योंकि आपके एम: एन संबंध के उदाहरणों के लिए गुण संलग्न हैं।
miroxlav

V4 GUIDS एक क्रिप्टोग्राफिक रूप से मजबूत PNRG का उपयोग करने की गारंटी नहीं है, इसलिए आपको वास्तव में अपने पहले उदाहरण imo के लिए इस पर भरोसा नहीं करना चाहिए (हालांकि यदि आपका डीबी इंजन मजबूत वादे करता है तो आप ठीक हो सकते हैं, लेकिन यह गैर पोर्टेबल है)। अन्यथा एक अच्छी तरह से तर्क पोस्ट।
वू

1
@miroxlav - यदि मैं एक तालिका में इस संबंध के बारे में पर्याप्त अतिरिक्त मेटाडेटा है कि दो FKs के बाहर एक अलग PK एक अच्छा विचार है, यह वास्तव में एक क्रॉस-संदर्भ तालिका नहीं है यह अपनी इकाई है जो दो अन्य को संदर्भित करने के लिए होता है।
कीथ्स

@Voo - आप सही कह रहे हैं, V4 GUIDs को क्रिप्टोग्राफिक रूप से यादृच्छिक होने की गारंटी नहीं है, बस अद्वितीय (जैसे सभी GUID हैं)। हालाँकि, अमेरिकी जेट सेनानियों की पूंछ संख्या क्रिप्टोग्राफिक रूप से यादृच्छिक बीज डेटा / एल्गोरिदम से उत्पन्न नहीं होती है। जो आप वास्तव में देख रहे हैं वह एक कम आबादी वाला डोमेन है; V4 GUID में यादृच्छिक डेटा के 112 बाइट्स हैं, जो 5e33 रिकॉर्ड की विशिष्ट पहचान करने में सक्षम हैं।
कीथ्स

परिप्रेक्ष्य में यह संख्या में कहें, हर आदमी, औरत और ग्रह पर बच्चे (सभी 7 अरब) 741 हो सकता था खरब अलग-अलग सूचीबद्ध और हमारे DB में डेटा बिंदुओं ided, और हम अभी भी केवल प्रति एक GUID मूल्य का उपयोग किया था अरब उपलब्ध। एक वैश्विक उद्योग के रूप में बिग डेटा, ज्ञान के इस पैमाने के करीब भी नहीं है। यहां तक ​​कि GUID पीढ़ी को एक पैटर्न दिया गया है, एन्ट्रापी के अन्य स्रोत भी शामिल हैं, जैसे कि जिस क्रम में डेटा सिस्टम में प्रवेश करता है और उसे GUID सौंपा जाता है।
कीथ्स

7

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

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

एक मामला जहां आप नहीं चाहते हैं कि एक ऑटो-इन्क्रीमेंटिंग कुंजी कई-से-कई टेबल होगी जहां प्राथमिक कुंजी दो अन्य तालिकाओं के आईडी कॉलम का एक कंपाउंड है (आप अभी भी यहां ऑटो-इंक्रीमेंटिंग कुंजी रख सकते हैं, लेकिन मैं इसकी बात नहीं देखते)।

एक अन्य प्रश्न ऑटो-इन्क्रिएट की गई कुंजी का डेटाटाइप है। Int32 का उपयोग करने से आपको मूल्यों की एक बड़ी, लेकिन अपेक्षाकृत सीमित सीमा मिलती है। व्यक्तिगत रूप से मैं अक्सर ईद के लिए बिगिंट कॉलम का उपयोग करता हूं, व्यावहारिक रूप से मूल्यों से बाहर चलने के बारे में चिंता करने की आवश्यकता नहीं है।


6

जैसा कि अन्य लोगों ने एक प्राथमिक वृद्धि के लिए मामला बनाया है मैं एक GUID के लिए एक बनाऊंगा:

  • यह अद्वितीय होने की गारंटी है
  • आप अपने आवेदन में डेटा के लिए डेटाबेस के लिए एक कम यात्रा कर सकते हैं। (उदाहरण के लिए एक प्रकार की तालिका के लिए आप GUID को एप्लिकेशन में संग्रहीत कर सकते हैं और रिकॉर्ड को पुनः प्राप्त करने के लिए उपयोग कर सकते हैं। यदि आप एक पहचान का उपयोग करते हैं तो आपको डेटाबेस को नाम से क्वेरी करने की आवश्यकता है और मैंने कई एप्लिकेशन देखे हैं जो पीके प्राप्त करने के लिए ऐसा करता है। और बाद में पूरी जानकारी प्राप्त करने के लिए फिर से पूछताछ करता है)।
  • यह डेटा छिपाने के लिए उपयोगी है। www.domain.com/Article/2 मुझे पता है कि आपके पास केवल दो लेख हैं जबकि www.domain.com/article/b08a91c5-67fc-449f-8a50-ffdf2403444a मुझे कुछ नहीं बताता है।
  • आप आसानी से विभिन्न डेटाबेस से रिकॉर्ड मर्ज कर सकते हैं।
  • MSFT पहचान के लिए GUIDS का उपयोग करता है।

संपादित करें: डुप्लिकेट बिंदु


5
-1। एक GUID / UUID अद्वितीय होने की गारंटी नहीं है, और 100% अद्वितीय नहीं है। एक GUID अभी भी एक परिमित लंबाई है, इसलिए कुछ बिंदु पर आप एक डुप्लिकेट प्राप्त करने का जोखिम उठा सकते हैं, हालांकि यह अत्यधिक संभावना नहीं है। डेटाबेस के लिए कम यात्राओं के बारे में आपकी बात भी अमान्य है - आप GUID कुंजी के साथ प्राथमिक आईडी स्टोर क्यों नहीं कर सकते?
निकल्स एच

2
जेफ एटवुड कहते हैं कि यह पहले से कहीं ज्यादा बेहतर है। blog.codinghorror.com/primary-keys-ids-versus-guids
तीन मान तर्क

जैसा कि आप अपने आवेदन में प्राथमिक आईडी क्यों नहीं जमा कर सकते हैं? क्योंकि डेटाबेस इसे बनाता है। यदि आप एक खाली डेटाबेस पर अपने बीज चलाते हैं तो आप मान सकते हैं कि आईडी 1 होगी। यदि आप डेटाबेस में उसी स्क्रिप्ट को डेटा के साथ चलाते हैं तो क्या होगा? आईडी 1 नहीं होगी
तीन वैल्यू लॉजिक

आपने एप्लिकेशन में आईडी बनाने के बारे में कुछ नहीं कहा - आपने सिर्फ "स्टोरिंग" लिखा है। लेकिन अगर डेटाबेस के बाहर आईडी बनाना जरूरी है, तो हां, एक GUID जवाब हो सकता है।
एच

2
मैं उन्हें बेहतर तरीके से जोड़ूंगा। कैसंड्रा जैसे बड़े डेटा NoSQL डेटाबेस भी ऑटो वेतन वृद्धि कुंजी का समर्थन नहीं करते।
कार्ल

2

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

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

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

यदि आपका डेटा केवल आपके डेटाबेस के भीतर एक जीवन होगा, तो ऑटो-इंक्रीमेंट पूर्णांक ठीक हैं। लेकिन, जैसा कि अन्य उत्तरों में उल्लेख किया गया है, यदि आप चाहते हैं कि आपका डेटा कभी भी साझा किया जाए, सिंक्रनाइज़ किया जाए, या अन्यथा आपके डेटाबेस से बाहर का जीवन हो, तो ऑटो-इंक्रीमेंट किए गए पूर्णांक खराब प्राथमिक कुंजी बनाते हैं। एक बेहतर विकल्प एक गाइड (उर्फ यूआईडी "सार्वभौमिक रूप से अद्वितीय आईडी") होगा।


2

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

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

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

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

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

योग करने के लिए, सभी तालिकाओं को सरोगेट कुंजी (किसी भी प्रकार की) की आवश्यकता नहीं होगी ; उन्हें केवल तब उपयोग किया जाना चाहिए जब विचार के तहत तालिका के प्रदर्शन के लिए आवश्यक समझा जाए। चाहे जो भी सामान्य सरोगेट कुंजी तकनीक आपको पसंद हो, एक विकल्प बनाने से पहले तालिका की वास्तविक जरूरतों के बारे में ध्यान से सोचें; एक मेज के लिए सरोगेट कुंजी प्रौद्योगिकी पसंद को बदलने का काम समाप्त हो जाएगा। अपनी तालिका के लिए मुख्य प्रदर्शन मीट्रिक का दस्तावेज़ करें ताकि आपके उत्तराधिकारी बने विकल्पों को समझ सकें।

विशेष स्थितियां

  1. यदि आपकी व्यावसायिक आवश्यकताएं उस क्षेत्र की तुलना में ऑडिट (या अन्य) उद्देश्यों के लिए लेनदेन की क्रमिक संख्या को अनिवार्य बनाती हैं, तो सरोगेट कुंजी नहीं है; यह एक प्राकृतिक कुंजी है (अतिरिक्त आवश्यकताओं के साथ)। प्रलेखन से एक ऑटो-इंक्रीमेंटिंग पूर्णांक केवल सरोगेट कुंजी बनाता है , इसलिए इसे उत्पन्न करने के लिए एक और तंत्र ढूंढें। स्पष्ट रूप से किसी प्रकार का मॉनिटर आवश्यक होगा, और यदि आप कई साइटों से अपने लेनदेन का सोर्स कर रहे हैं, तो एक साइट विशेष होगी , जो मॉनिटर के लिए नामित होस्ट साइट होने के आधार पर होगी।

  2. यदि आपकी तालिका कभी भी लगभग सौ पंक्तियों से अधिक नहीं होगी, तो सूचकांक ऊंचाई अप्रासंगिक है; हर एक्सेस टेबल स्कैन द्वारा होगा। हालांकि, लंबे तार पर स्ट्रिंग तुलना अभी भी 4-बाइट पूर्णांक की तुलना में बहुत अधिक महंगी होगी, और GUID की तुलना में अधिक महंगी होगी।

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


-1

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

प्रत्येक तालिका को एक pseudokey की आवश्यकता नहीं है - एक प्राथमिक कुंजी एक मनमाना मूल्य के साथ, कुछ ऐसा नहीं है जो मॉडल के लिए शब्दार्थ मूल्य है - और हमेशा इसे कॉल करने का कोई कारण नहीं है id


ऐसा लगता है कि किए गए अंकों से अधिक कुछ भी नहीं दिया जा रहा है और पहले 9 जवाबों में समझाया गया है
gnat

2
और यह महत्वपूर्ण क्यों हो सकता है?
gnat

3
@gnat क्योंकि यह सर्वोत्तम प्रथाओं पर एक पुस्तक है, जो सीधे प्रश्न को संबोधित करती है। क्या यह स्पष्ट नहीं है?
पेड्रो वर्नैक

3
मामूली नहीं। "पुस्तक एसक्यूएल सर्वोत्तम प्रथाओं" के लिए Google खोज मेरे बारे में 900K लिंक दिखाती है, यह विशेष रूप से योग्य क्यों होगा
gnat

1
@gnat मैं पूरे दिन बहस करने वाला नहीं हूं। आपको उत्तर पसंद नहीं है, यही कारण है कि डाउनवोट्स हैं।
पेड्रो वेर्ने

-2

यह बहुत सार्वभौमिक है - अन्यथा आपको यह सत्यापित करने की आवश्यकता होगी कि कुंजी वास्तव में अद्वितीय है। यह अन्य सभी चाबियों को देखकर किया जाएगा ... जो समय लेने वाली होंगी। वृद्धिशील कुंजी होने के कारण आपका रिकॉर्ड नंबर महंगे ओवरफ्लो मूल्य के पास महंगा हो जाता है।

मैं आमतौर पर संकेतकर्ताओं को अधिक स्पष्ट फ़ील्ड नाम जैसे ref_{table}या समान विचार बनाता हूं ।

यदि इसकी आवश्यकता बाहरी रूप से रिकॉर्ड करने की ओर नहीं है, तो आपको आईडी की आवश्यकता नहीं है।


मुख्य रोलओवर मान?
AJJ

एक अहस्ताक्षरित पूर्णांक में 4294967295 का अधिकतम मूल्य है, 1 को जोड़ने से पहले इसे 0. से अधिक रोल किया जाएगा। याद रखें यदि आप एक रिकॉर्ड जोड़ते हैं तो इसे हटा दें, काउंटर अभी भी बढ़ा हुआ है। सुनिश्चित करें कि आप unsigned intफ़ील्ड प्रकार के लिए उपयोग करते हैं अन्यथा सीमा उस संख्या का आधा है।
जॉनी वी

इंटेगर ओवरफ्लो - en.wikipedia.org/wiki/Integer_overflow
जॉनी V

2
यदि आप बहुत सारी पंक्तियों को जोड़ते / हटाते हैं तो ऑटो इंक्रीमेंट काउंटर अंततः ओवरफ्लो हो जाएगा।
जॉनी वी

1
लोग रोलओवर कैसे संभालते हैं? क्या होगा अगर कम आईडी वाले रिकॉर्ड हैं जो कभी डिलीट नहीं होते हैं, लेकिन आप उस अंत के पास पहुंचने लगे हैं जहां कुछ आईडी 4294967295 के ऊपरी छोर पर हैं? क्या "पुन: अनुक्रमण" किया जा सकता है?
AJJ

-2

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


-3

एक प्राथमिक कुंजी के लिए एक ऑटो वेतन वृद्धि काउंटर एक अच्छा विचार नहीं है। ऐसा इसलिए है क्योंकि आपको अपना डेटा डालने से पहले अगली कुंजी और वेतन वृद्धि के लिए डेटाबेस में वापस जाने की आवश्यकता है।

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

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

बेशक सभी डेटाबेस इसका समर्थन नहीं करते हैं। जिस स्थिति में मैं आम तौर पर एक मेज का उपयोग करता हूं जो कुंजी बाल्टियों को संग्रहीत करता है और उच्च और निम्न श्रेणियों का उपयोग करता है जो अनुप्रयोग में प्रबंधित होते हैं। यह सबसे अच्छा समाधान है जो मुझे लगता है क्योंकि आपको 10000 नंबर की एक श्रृंखला मिलती है और ऑटो उन्हें आवेदन के उदाहरण पर बढ़ाता है। एक अन्य एप्लिकेशन इंस्टेंस के साथ काम करने के लिए नंबर की एक और बाल्टी ले सकते हैं। आपको 64-बिट लंबे समय के लिए पर्याप्त रूप से बड़ी प्राथमिक कुंजी आदिम की आवश्यकता होती है।

UUIDs मैं प्राथमिक कुंजी के रूप में उपयोग नहीं करता हूं क्योंकि उन्हें बनाने और उन्हें संग्रहीत करने की लागत एक के बाद एक लंबे मूल्य को बढ़ाने से बहुत अधिक है। UUIDs अभी भी जन्मदिन के विरोधाभास से निपटते हैं कि एक डुप्लिकेट सैद्धांतिक रूप से उत्पन्न हो सकता है।


3
नहीं, ऑटो-इन्क्रीमेंट कीज़ का अर्थ है कि कुंजी का इन्क्रीमेंट डेटाबेस द्वारा स्वचालित रूप से किया जाता है। कभी-कभी (मैं आपको देख रहा हूं, ओरेकल!) ऐसा करने के लिए आपको एक अनुक्रम + ट्रिगर संयोजन की आवश्यकता है, लेकिन आपको कभी भी कुंजी के लिए पहले से डाला गया मूल्य देखने की जरूरत नहीं है, 1 जोड़ें, फिर इसका उपयोग करें।
SQB

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