एक प्राथमिक कुंजी के रूप में एक GUID का उपयोग करना


32

मैं आमतौर पर डेटाबेस में प्राथमिक वेतन वृद्धि के रूप में ऑटो वेतन वृद्धि आईडी का उपयोग करता हूं। मैं GUID का उपयोग करने के लाभों को सीखने की कोशिश कर रहा हूं। मैंने यह लेख पढ़ा है: https://betterexplained.com/articles/the-quick-guide-to-guids/

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

public class Person
{
public GUID ID;
public string Name;
..

//Person Methods follow
}

कहते हैं कि मैं एक नया व्यक्ति बनाना चाहता था और फिर व्यक्ति को एक डेटाबेस में सम्मिलित करना चाहता था। क्या मैं ऐसा कर सकता हूँ:

Person p1 = new Person();
p1.ID=GUID.NewGUID();
PersonRepository.Insert(p1);

कहो कि मेरे पास एक डेटाबेस था जिसमें प्राथमिक कुंजी के रूप में एक GUID के साथ लाखों और लाखों पंक्तियाँ थीं। क्या यह हमेशा अनूठा होगा? क्या मैं GUID को सही ढंग से समझ रहा हूं?

मैंने इस लेख को पहले पढ़ा: http://enterprisecraftsmanship.com/2014/11/15/cqs-with-database-generated-ids/ । यह मुझे थोड़ा भ्रमित करता है क्योंकि यह प्राथमिक कुंजी के रूप में GUID और पूर्णांक के बीच एक खुश माध्यम की सिफारिश करता प्रतीत होता है।

संपादित करें 11/06/18

मुझे विश्वास है कि Guids मेरी आवश्यकताओं के लिए ints से अधिक उपयुक्त हैं। मैं इन दिनों CQRS का उपयोग कर रहा हूं और GUID अधिक अच्छी तरह से फिट होते हैं।

मैं ध्यान देता हूं कि कुछ डेवलपर्स GUID को डोमेन मॉडल में स्ट्रिंग के रूप में मॉडल करते हैं जैसे यहाँ: https://github.com/dotnet-Healthecture/eShopOnContainers/blob/dev/src/Services/Or/ing/Ordering.Domain/AggregatesModel/BuyerAggregate/ Buyer.cs - इस मामले में: IdentityGuid एक GUID है जिसे एक स्ट्रिंग के रूप में बनाया गया है। क्या यहां बताए गए के अलावा ऐसा करने का कोई कारण है: किसी वितरित सिस्टम में एक कस्टम आइडेंटिफायर के रूप में कस्टम वैल्यू ऑब्जेक्ट या गाइड का उपयोग करें? । क्या GUID को एक स्ट्रिंग के रूप में मॉडल करना "सामान्य" है या क्या मुझे मॉडल और डेटाबेस में GUID के रूप में मॉडलिंग करनी चाहिए?



7
अद्वितीय होने की गारंटी नहीं है, हालांकि यह संभावना नहीं है कि आप कभी टकराव देखेंगे। stackoverflow.com/questions/1155008/how-unique-is-uuid/…
icirellik

2
इसे भी देखें: UUID टकराव
gnat

2
यह भी देखें dba.stackexchange.com/questions/54690/… , साथ ही साथ कई अन्य प्रश्न - इस विषय को पूछा गया है, और उत्तर दिया गया है, और अक्सर इसके बारे में तर्क दिया जाता है।
ग्रीनस्टोन वॉकर

1
सिस्टम मैं इस समय के साथ काम कर रहा हूँ UUIDs का उपयोग करता है। एक अच्छी संपत्ति यह है कि एक आईडी एक रिकॉर्ड को विशिष्ट रूप से पहचानती है, जैसा कि एक अनुक्रमिक आईडी के विपरीत है जो उस तालिका में रिकॉर्ड की पहचान करता है।
जस्टिन

जवाबों:


41

GUIDs "ग्लोबली यूनिक IDentifiers" परिभाषा के अनुसार हैं। जावा में एक समान लेकिन थोड़ा अलग अवधारणा है जिसे यूयूआईडीएस कहा जाता है "यूनीलीली यूनिक आईडीएंटिफायर"। सभी व्यावहारिक उपयोग के लिए नाम विनिमेय हैं।

GUID केंद्रीय हैं कि कैसे Microsoft ने डेटाबेस को काम करने की कल्पना की है, और यदि आपको कभी-कभी जुड़े स्रोतों से डेटा को शामिल करने की आवश्यकता है, तो वे वास्तव में डेटा टकराव को रोकने में मदद करते हैं।

कुछ प्रो-GUID तथ्य:

  • GUID कुंजी टकराव को रोकते हैं
  • GUID नेटवर्क, मशीनों आदि के बीच डेटा को मर्ज करने में मदद करते हैं।
  • एसक्यूएल सर्वर ने सूचकांक विखंडन को कम करने में मदद करने के लिए अर्ध-अनुक्रमिक जीयूआईडी का समर्थन किया है ( रेफरी , कुछ कैविट्स )

GUIDs के साथ कुछ उतावलापन

  • वे बड़े हैं, प्रत्येक 16 बाइट्स
  • वे ऑर्डर से बाहर हैं, इसलिए आप आईडी पर सॉर्ट नहीं कर सकते हैं और आप ऑटो-इंक्रीमेंट आईडी पर अपनी तरह इंसर्शन ऑर्डर प्राप्त करने की उम्मीद कर सकते हैं
  • वे काम करने के लिए अधिक बोझिल हैं, विशेष रूप से छोटे डेटा सेट पर (जैसे टेबल देखें)
  • नई GUID कार्यान्वयन SQL सर्वर पर C # लाइब्रेरी में होने से अधिक मजबूत है (आप SQL सर्वर से क्रमिक GUIDS हो सकते हैं, C # में यह यादृच्छिक है)

GUID आपके अनुक्रमणिका को बड़ा बना देंगे, इसलिए किसी स्तंभ को अनुक्रमित करने की डिस्क स्थान लागत अधिक होगी। रैंडम GUIDs आपके अनुक्रमित टुकड़े कर देंगे।

यदि आप जानते हैं कि आप विभिन्न नेटवर्कों से डेटा को सिंक्रनाइज़ करने के लिए नहीं जा रहे हैं, तो GUID अधिक मूल्य की तुलना में अधिक ओवरहेड ले जा सकते हैं।

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


18
मेरी समझ यह है कि GUIDs UUIDs का पर्याय हैं। यूयूआईडी मानक नाम है। GUID वह है जो Microsoft ने RFC 4122 से पहले गढ़ा था ।
जिमीजम्स

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

8
@CortAmmon विकिपीडिया और RFC 4122 के अनुसार , वे पर्यायवाची हैं। Microsoft का पी। लीच RFC के रचनाकारों में से एक था। मुझे लगता है कि जब से RFC बना था, दोनों एक ही हैं। RFC से: "UUIDs (यूनिवर्सली यूनिक IDentifier), जिसे GUIDs (ग्लोबली यूनिक IDentifier) ​​के रूप में भी जाना जाता है।" मुझे लगता है कि यह भी ध्यान रखना उपयोगी है कि GUIDs MS द्वारा नहीं बनाए गए थे। उन्होंने बस कहीं और से अपनाई गई तकनीक के लिए एक नया नाम बनाया।
जिमीजम्स

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

7
"SQL सर्वर में GUID से निपटने के लिए अनुकूलन है, इसलिए यह क्वेरी प्रदर्शन को अधिक प्रभावित नहीं करना चाहिए। " सच नहीं है। यह कथन मानता है कि अन्य डेटा प्रकार अनुकूलित नहीं हैं। डेटाबेस सर्वरों में सरल अंतर मूल्यों से निपटने के लिए अनुकूलन भी हैं, उदाहरण के लिए। GUIDs / UUIDs 4-बाइट int मान का उपयोग करने की तुलना में बहुत धीमी हैं। 16 बाइट्स कभी भी 4 बाइट्स के रूप में तेज़ नहीं होंगे - विशेष रूप से एक मशीन पर जो मूल रूप से 4 या 8 बाइट्स को संभालती है।
एंड्रयू हेनले

28

क्या यह हमेशा अनूठा होगा?

हमेशा? नहीं, हमेशा नहीं; यह बिट्स का एक परिमित अनुक्रम है।

कहो कि मेरे पास एक डेटाबेस था जिसमें प्राथमिक कुंजी के रूप में एक GUID के साथ लाखों और लाखों पंक्तियाँ थीं।

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

क्या मैं ऐसा कर सकता हूं?

आप ऐसा कर सकते हैं; यह पूरी तरह से अच्छा विचार नहीं है। आपका डोमेन मॉडल आम तौर पर यादृच्छिक संख्या उत्पन्न नहीं करना चाहिए; उन्हें आपके मॉडल के लिए इनपुट होना चाहिए।

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

RFC 4122 में नाम-आधारित यूआईडी का विवरण देखें

क्या GUID को एक स्ट्रिंग के रूप में मॉडल करना "सामान्य" है या क्या मुझे मॉडल और डेटाबेस में GUID के रूप में मॉडलिंग करनी चाहिए?

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

यदि GUID आपके डोमेन अज्ञेय सेटिंग में "आदिम प्रकार" के रूप में उपलब्ध है, तो मैं इसका उपयोग करूंगा; यह सहायक संदर्भ को उपयुक्त अनुकूलन चुनने की अनुमति देता है जो उपलब्ध हो सकता है।

हालांकि, आपको जो पहचानना चाहिए, वह यह है कि पहचानकर्ता का प्रतिनिधित्व, मेमोरी और स्टोरेज दोनों में, एक निर्णय है जिसे आप अपने कार्यान्वयन में कर रहे हैं, और इसलिए आपको यह सुनिश्चित करने के लिए कदम उठाने चाहिए कि कोड का फुट प्रिंट उससे युग्मित हो। निर्णय छोटा है - देखें पारस 1972


20
+1 के लिए "आप पहले से ही डिस्क स्थान से बाहर चले जाते हैं जो तब होता है।"
w0051977

2
मुझे लगता है "की अवधारणा को निर्धारणात्मक उत्पन्न UUID " आवश्यक है (देखें डाटा वॉल्ट 2)
ALK

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

एक मिलियन लाखों = 2 ^ 40। यह संभव टकरावों के 2 ^ 79 जोड़े बनाता है। GUID में 2 ^ 128 बिट्स हैं, इसलिए मौका 2 ^ 49 में से एक है। यह बहुत अधिक संभावना है कि आपके पास एक बग है जो दो रिकॉर्ड के लिए एक ही GUID का पुन: उपयोग करता है, या कि गलती से मानता है कि एक टक्कर है जहां कोई नहीं है।
gnasher729 21

मैं अपने ऐतिहासिक सवालों से पीछे हट रहा हूं। मेरे स्वीकार करने से पहले; क्या आप मेरे संपादन पर एक नज़र डाल सकते हैं?
w0051977

11

GUID या UUID बहुत ही विशिष्ट होंगे क्योंकि वे कैसे उत्पन्न होते हैं और वे केंद्रीय प्राधिकरण के साथ संवाद किए बिना विशिष्टता की गारंटी के लिए एक सुरक्षित तरीका प्रदान करते हैं।

प्राथमिक कुंजी के रूप में GUID का लाभ:

  • आप किसी क्लस्टर के विभिन्न शेड्स के बीच डेटा कॉपी कर सकते हैं और PK टकराव के बारे में चिंता करने की आवश्यकता नहीं है।
  • इससे पहले कि आप किसी भी रिकॉर्ड को डालने से पहले अपनी प्राथमिक कुंजी को जान सकें।
  • बाल रिकॉर्ड सम्मिलित करने के लिए लेनदेन तर्क को सरल करता है।
  • आसानी से अनुमान नहीं लगाया जा सकता है।

आपके द्वारा दिए गए उदाहरण में:

Person p1 = new Person();
p1.ID = GUID.NewGUID();
PersonRepository.Insert(p1);

प्रविष्टि समय से पहले GUID को निर्दिष्ट करना क्रमिक बच्चे के रिकॉर्ड को सम्मिलित करते समय डेटाबेस के लिए एक गोल यात्रा को बचा सकता है और आपको एक ही लेनदेन में उन्हें प्रतिबद्ध करने की अनुमति दे सकता है।

Person p2 = new Person();
p2.ParentID = p1.ID
PersonRepository.Insert(p2);

प्राथमिक कुंजी के रूप में GUIDs की पहचान:

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

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

कई डेटाबेस के अपने आंतरिक कार्यान्वयन हैं जो GUID और SQL सर्वर के कारण स्टोरेज की समस्याओं को कम करने का प्रयास करते हैं, यहां तक ​​कि UUID के अनुक्रमणिका के बेहतर उपयोग की अनुमति देने के क्रम में मदद करने के लिए एक फ़ंक्शन नया परिणाम भी है और उनके पास आमतौर पर बेहतर प्रदर्शन विशेषताएँ हैं।

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

अंत में, जब तक कि बड़े पैमाने पर क्लस्टरिंग या URL को बाधित नहीं करना एक आवश्यकता है, ऑटो-इंक्रीमेंटिंग आईडी के साथ रहना अधिक व्यावहारिक है।


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

सहमत, हालांकि किसी को URL में अपनी प्राथमिक कुंजी को उजागर नहीं करना चाहिए। यह सुनिश्चित करने के लिए कुछ अधिक उपयुक्त विधि का उपयोग किया जाना चाहिए कि बाहरी
सिस्टम पर

1
एक और उपयोग मामला है: भारी डालने वाले ओएलटीपी डेटाबेस जिसमें अनुक्रम के लिए लॉकिंग एक अड़चन है। मेरे ओरेकल डीबीए दोस्त के अनुसार, यह उतना दुर्लभ नहीं है जितना यह लगता है, आपको इसके लिए बड़े पैमाने या क्लस्टर की भी आवश्यकता नहीं है। • अंत में, पेशेवरों और विपक्षों को तौलना (और पेशेवरों / विपक्षों के साथ UUIDs के विपक्ष / विपक्ष को भ्रमित न करें जो कि UUIDs के लिए विशिष्ट नहीं हैं जैसा कि कुछ पोस्टर करते हैं) और मापते हैं
mirabilos

1
यदि आप newfterentialid का उपयोग करते हैं तो आपको आईडी प्राप्त करने के लिए db पर जाना होगा (जैसे पहचान पहचान के साथ), क्या आप नहीं? यहाँ क्या लाभ है।
w0051977

1
@mirabilos स्पष्ट होने के लिए, जब मैं कहता हूं कि हम भयानक थे जो आवेषण प्रति मिनट मिनट ले रहे थे । यह ठीक है, लेकिन 10 पंक्तियों की हजारों की संख्या के बाद, यह वास्तव में तेजी से बग़ल में चला गया। यदि यह स्पष्ट नहीं है, तो हजारों पंक्तियों की 10s एक बहुत छोटी तालिका है।
जिम्मीजम्स 15

4

मैं कहूंगा कि प्राथमिक कुंजी के रूप में GUID का उपयोग न करें। मैं वास्तव में अब ऐसे डीबी के साथ काम कर रहा हूं, और वे प्रदर्शन के मुद्दों के प्राथमिक कारणों में से एक हैं।

अतिरिक्त 12 बाइट्स जल्दी से जोड़ते हैं; याद रखें, अधिकांश पीके अन्य तालिकाओं में एफके होंगे, और एक तालिका में सिर्फ तीन एफके आपके पास अब हर पंक्ति में 48 बाइट्स अतिरिक्त हैं। यह तालिका में और अनुक्रमित में जोड़ता है। यह डिस्क I / O में भी जुड़ जाता है। उन अतिरिक्त 12 बाइट्स को पढ़ने और लिखने की आवश्यकता है।

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

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


4
Person p1 = new Person();
p1.ID=GUID.NewGUID();
PersonRepository.Insert(p1);

यह GUID का उपयोग करने का सबसे महत्वपूर्ण कारण है।

तथ्य यह है कि आप अपने कोड के बारे में जाने या अपनी दृढ़ता परत के साथ संचार के बिना एक अद्वितीय आईडी बना सकते हैं एक बहुत बड़ा लाभ है।

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

आप इसे किसी भी तरह के डेटाबेस rdb या no-sql, फ़ाइल में चिपका सकते हैं, इसे किसी भी वेबसाइट पर भेज सकते हैं या बिना बताए इसे तुरंत फेंक सकते हैं

नहीं, आपको कभी टक्कर नहीं मिलेगी।

हां आवेषण थोड़ा धीमा हो सकता है क्योंकि सूचकांक को इसके साथ भरा जाना पड़ सकता है।

हाँ यह एक इंट से बड़ा है।

  • संपादित करें। खत्म करने से पहले शूट करना पड़ा।

मुझे पता है कि बहुत से लोग ऑटो इंक चींटियों के बारे में दृढ़ता से महसूस करते हैं और यह डीबीए के साथ एक विवादास्पद विषय है

लेकिन मैं वास्तव में पर्याप्त रूप से पर्याप्त नहीं कर सकता कि कैसे बेहतर छापे हैं। आपको किसी भी एप्लिकेशन में डिफ़ॉल्ट रूप से गाइड का उपयोग करना चाहिए ।

ऑटो इंक चींटियों में कई खामियां हैं

  • आप एक नो-एसक्यूएल वितरित डीबी का उपयोग करें। आप बस यह जानने के लिए कि अगले नंबर का क्या है, अन्य सभी उदाहरणों से बात नहीं कर सकते।

  • आप एक संदेश कतार प्रणाली का उपयोग करें। Db को हिट करने से पहले चीजों को ID की आवश्यकता होती है

  • आप कई आइटम बना रहे हैं और सहेजने से पहले उन्हें संपादित कर रहे हैं। Db को हिट करने से पहले प्रत्येक को एक आईडी की आवश्यकता होती है

  • आप पंक्तियों को हटाना और पुन: सम्मिलित करना चाहते हैं। सुनिश्चित करें कि आप अपने ऑटो इंक आईडी की गिनती नहीं करते हैं और बाहर नहीं चलते हैं!

  • आप इस बात को उजागर नहीं करना चाहते हैं कि आपने प्रत्येक उपयोगकर्ता को इस वर्ष कितने आदेश दिए हैं

  • आप अनाम डेटा को उत्पादन से लेकर परीक्षण और रिश्तों को अक्षुण्ण बनाए रखना चाहते हैं। लेकिन सभी मौजूदा परीक्षण डेटा को नहीं हटाएं।

  • आप अपने एकल किरायेदार उत्पाद को एक बहु किरायेदार डेटाबेस में विलय करना चाहते हैं, लेकिन हर किसी का ऑर्डर 56 है।

  • आप ऐसी वस्तुओं का निर्माण करते हैं जो स्थायी होती हैं लेकिन अल्पकालिक होती हैं। (अपूर्ण आदेश) फिर से, सामान के साथ अपने सभी किलों का उपयोग न करें जो अब मौजूद नहीं है।

सूची अंतहीन है और वे सभी वास्तविक समस्याएं हैं जो हर समय लोगों को होती हैं। थोड़ा बड़ा एफके कोल की वजह से डिस्कस्पेस से बाहर चलने के विपरीत

अंत में चींटियों के साथ बड़े पैमाने पर मुद्दा आप उनमें से बाहर चला रहे हैं !!! ठीक है न सिद्धांत में, तुम भार हो। लेकिन व्यवहार में आप ऐसा इसलिए करते हैं क्योंकि लोग उन्हें बिना किसी मतलब के यादृच्छिक संख्याओं की तरह मानते हैं। वे बातें करते हैं

  • ओह, मैं नहीं चाहता कि ग्राहक यह सोचें कि हम नए हैं। 10,000 से शुरू करें

  • मुझे डेटा का एक भार आयात करना था इसलिए मैंने बीज को 1 मीटर तक छोड़ दिया ताकि हम जान सकें कि आयात क्या है

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

  • मैंने नए आईडी के साथ फिर से सभी डेटा को हटा दिया और फिर से हटा दिया। हां, ऑडिट भी लॉग होता है।

  • इस नंबर का उपयोग करें, जो कि एक कंपोजिट कुंजी है, इस अन्य चीज़ की आईडी के रूप में


1
इस उत्तर के साथ तथ्यात्मक रूप से कुछ भी गलत नहीं है, लेकिन मैं (आगे की गिरावट को दूर करने के लिए) शायद स्पष्ट रूप से स्पष्ट कर दूंगा कि भले ही वास्तविक जीवन में टकरावों का सामना न करें, यह सैद्धांतिक रूप से संभव है। (या शायद ४५+ एक्साबाइट डेटाबेस मेरे विचार से अधिक प्रचलित हैं ...)। हालांकि मुझे लगता है कि भाषा "सबसे महत्वपूर्ण कारण" थोड़ा मजबूत है, यही वह है जो मुझे सबसे उपयोगी लगता है।
BurnsBA

2
इसकी अधिक संभावना है कि एक ऑटो इंक इंट एक गाइड
ईवान

4
-1 के लिए "आपको किसी भी एप्लिकेशन में डिफ़ॉल्ट रूप से छापे का उपयोग करना चाहिए।" यह ™ पर निर्भर करता है। और जैसा कि दूसरों ने दिखाया है, GUIDs / UUIDs, बिल्कुल अद्वितीय होने की गारंटी नहीं हैं।
मैक्स वर्नोन

3
"यह निर्भर करता है" उत्तर बेकार हैं, यकीन है कि कुछ अजीब अनुप्रयोग होने जा रहे हैं जहां एक इंट बेहतर है। लेकिन संभावना है कि आपके आवेदन उनमें से एक नहीं है। GUIDs सबसे अनोखी चीज है जो आप पा सकते हैं
Ewan

2
मुझे लगता है कि कुछ विषम अनुप्रयोग होंगे जहां छापे बेहतर हैं। अनोखा सबसे महत्वपूर्ण बात नहीं है। किलों की आपकी "खामियां" बड़े पैमाने पर खत्म हो जाती हैं, और आप गाइड के कई डाउनसाइड्स में से किसी पर भी विचार नहीं करते हैं।
एंडी

2

मुझे लगता है कि इन GUID का उपयोग अनुप्रयोग स्तर पर वस्तुओं की पहचान करने के लिए किया जाता है। क्या उन्हें डेटाबेस स्तर पर प्राथमिक कुंजी के रूप में संग्रहीत किया जाता है।

वहीं आपको रुकना चाहिए, वहीं, और पुनर्विचार करना चाहिए।

आपके डेटाबेस की प्राथमिक कुंजी को कभी भी व्यावसायिक अर्थ नहीं होना चाहिए। इसे परिभाषा से निरर्थक होना चाहिए।

तो GUID को अपनी व्यावसायिक कुंजी और सामान्य प्राथमिक कुंजी (आमतौर पर एक लंबी int) डेटाबेस प्राथमिक कुंजी के रूप में जोड़ें। विशिष्टता को सुनिश्चित करने के लिए आप हमेशा GUID पर एक अद्वितीय सूचकांक रख सकते हैं।

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


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

@icirellik प्राथमिक कुंजी डेटाबेस द्वारा आंतरिक उपयोग के लिए है, माता-पिता और बच्चे के रिकॉर्ड और इस तरह लिंक करने के लिए। यह एप्लिकेशन लॉजिक द्वारा उपयोग के लिए नहीं है, आप इसके लिए व्यावसायिक आईडी का उपयोग करते हैं, जैसे कि उत्पाद संख्या या नाम।
jwenting

2

हमेशा उत्पन्न डेटाबेस, ऑटो-इंक्रीमेंटिंग प्राइमरी कीज़ (पीके) का उपयोग करें।

GUID / UUID के बजाय स्वतः-वृद्धि का उपयोग क्यों करें?

  • GUID (UUID) महत्वपूर्ण टकरावों को नहीं रोकते हैं क्योंकि वे अद्वितीय नहीं हैं और उन्हें अद्वितीय बनाने का कोई तरीका नहीं है क्योंकि वे कई स्रोतों से उत्पन्न होते हैं।
  • GUIDs विलय के साथ मदद नहीं करते हैं क्योंकि वे पहले से ही समय लेने वाली विलय प्रक्रिया को बहुत लंबे, गैर-पूर्णांक PK और FK स्तंभों के साथ बढ़ाते हैं जो प्रक्रिया में बहुत समय लेते हैं। याद रखें कि अधिकांश पीके के लिए, कम से कम 1 अन्य तालिका एक ही आकार की कम से कम 2 कुंजियों के साथ होगी: यह खुद पीके है और पहली तालिका में वापस एफके है। सभी को एक मर्ज में हल करना होगा।

लेकिन फिर शार्क, क्लस्टर्स आदि को कैसे संभालना है?

  • प्रत्येक शर्ड / क्लस्टर / डेटाबेस / जो कुछ भी प्रबंधित करता है, उसे पहचानने के लिए अलग-अलग कॉलमों से बने मल्टी-कॉलम पीके बनाएं जो स्वयं की-इंक्रीमेंटिंग कीज़ हैं। उदाहरण के लिए...

एक क्लस्टर तालिका के लिए 3-स्तंभ पीके हो सकता है ...

 DB | SH | KEY     |
----|----|---------|
 01 | 01 | 1234567 |

लेकिन क्या बारे में...?

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

  • प्रदर्शन - कंप्यूटर एक पूर्णांक (10) बनाम GUID (37) में संभव मानों की तुलना में बहुत बड़े डोमेन की वजह से सरल पूर्णांकों को किसी अन्य चीज़ की तुलना में कहीं अधिक तेजी से संसाधित कर सकते हैं। यह भी याद रखें कि GUID में प्रत्येक वर्ण को पहले CPU द्वारा हेरफेर किए जाने वाले नंबर में परिवर्तित किया जाना चाहिए।

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

गुम रिकॉर्ड्स का पता लगाना

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

छंटाई

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

टेबल स्कीमा पर आपके विचार ऐसे हैं कि एकमात्र अनूठा कॉलम एक डेटाबेस-निर्मित ऑटो-इन्क्रिमिंग प्राथमिक कुंजी है? विशेष रूप से उन तालिकाओं के लिए जिनके पास कोई विदेशी कुंजी नहीं है, लेकिन जिनकी प्राथमिक कुंजी कई संबंधित तालिकाओं के लिए विदेशी कुंजी है?
रिबेल्डएडीडी

मैंने उन पंक्तियों के साथ उत्तर में बहुत कुछ जोड़ा है। Android SE ऐप मैं लटकने के कारण मूल उत्तर अधूरा था। मुझे लगता है कि ऐप का एक प्रमुख पुनर्लेखन विकास में है।
DocSalvager

तो आपके विचार में किसी भी संख्या में उन पंक्तियों को शामिल करना एक तालिका के लिए ठीक होगा जो उनकी ऑटो-इन्क्रिमिंग प्राथमिक कुंजी के लिए समान रूप से सहेजे गए थे?
रिबॉल्डएडीडी

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

1

कुछ भी करने के लिए, ऐसा करने के फायदे और नुकसान हैं:

अच्छा:

  1. आपकी कुंजी हमेशा एक ही लंबाई की होती है (बहुत बड़े डेटाबेस में बहुत बड़ी कुंजी हो सकती है)

  2. विशिष्टता की बहुत अधिक गारंटी है - यहां तक ​​कि जब आप उन्हें एक अलग सिस्टम से उत्पन्न कर रहे हैं, और / या डेटाबेस से अंतिम आईडी नहीं पढ़ी है

खराब:

  1. जैसा कि ऊपर बताया गया है - बड़े सूचकांक और डेटा स्टोर।

  2. आप आईडी द्वारा ऑर्डर नहीं कर सकते, आपको कुछ और करके ऑर्डर करना होगा। अधिक अनुक्रमित, शायद कम कुशल।

  3. वे मानव पठनीय कम हैं। आम तौर पर लोगों को पार्स करना, याद रखना और लोगों के लिए टाइप करना आसान होता है। कई शामिल किए गए तालिकाओं में पूरे खंड में ID के रूप में GUID का उपयोग करना आपके सिर को पिघला सकता है।

सब कुछ की तरह, उनका उपयोग करें जहां उपयुक्त हो, डोगमैटिक न हों - कई स्थितियों में ऑटो-इंक्रीमेंटिंग पूर्णांक बेहतर होते हैं, कभी-कभी GUID बहुत अच्छे होते हैं।


0

हाँ आप प्राथमिक कुंजी के रूप में GUID का उपयोग कर सकते हैं। डाउन साइड इंडेक्स का आकार और तेजी से विखंडन है।

जब तक आपको डेटाबेस (जैसे एक क्लस्टर) पूर्णांक पसंद नहीं किया जाता है, तब तक विशिष्टता की आवश्यकता होती है।


GUID जनरेटर एक से अधिक बार एक ही GUID का उत्पादन कर सकते हैं, जिसमें एक दोष है। वे मुख्य रूप से घड़ी की टिक के बीच के अंतराल पर, उनकी ग्रैन्युलैरिटी पर निर्भर करते हैं या नहीं। उदाहरण के लिए, घड़ी आधारित जनरेटर केवल प्रत्येक 100ms पर टिक कर सकता है, जिससे उस मशीन पर 100 मीटर के भीतर 2 GUID का अनुरोध किया जा सकता है। इससे बचने के तरीके हैं, ज्यादातर, लेकिन कई GUID जनरेटर पूरी तरह से IP पते और / या मैक पते और एक टाइमस्टैम्प से दूर काम करते हैं।
jwenting

0

यहाँ मेरा इस मुद्दे पर समाधान है - समाधान GUID और अंतर मूल्यों के बीच एक आधा घर है, दोनों का सबसे अच्छा लेना।

कक्षा एक छद्म यादृच्छिक (लेकिन समय के साथ बढ़ते हुए) Id मान उत्पन्न करता है, जो एक संयोजन GUID के समान है ।

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

उत्पन्न मान GUID के लिए 16 के बजाय केवल 8 बाइट्स का उपयोग करते हैं, और एक विशिष्ट डेटाबेस सॉर्ट क्रम (जैसे GUID के लिए Sql सर्वर ) पर निर्भर नहीं होते हैं । पूरे अहस्ताक्षरित लंबी सीमा का उपयोग करने के लिए मूल्यों का विस्तार किया जा सकता है, लेकिन यह किसी भी डेटाबेस या अन्य डेटा भंडार के साथ मुद्दों का कारण होगा जो केवल पूर्णांक प्रकारों पर हस्ताक्षर किए हैं।

public static class LongIdGenerator
{
    // set the start date to an appropriate value for your implementation 
    // DO NOT change this once any application that uses this functionality is live, otherwise existing Id values will lose their implied date
    private static readonly DateTime PeriodStartDate = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    private static readonly DateTime PeriodEndDate = PeriodStartDate.AddYears(100);
    private static readonly long PeriodStartTicks = PeriodStartDate.Ticks;
    private static readonly long PeriodEndTicks = PeriodEndDate.Ticks;
    private static readonly long TotalPeriodTicks = PeriodEndTicks - PeriodStartTicks;

    // ensures that generated Ids are always positve
    private const long SEQUENCE_PART_PERMUTATIONS = 0x7FFFFFFFFFFF; 

    private static readonly Random Random = new Random();

    private static readonly object Lock = new object();
    private static long _lastSequencePart;

    public static long GetNewId()
    {
        var sequencePart = GetSequenceValueForDateTime(DateTime.UtcNow);

        // extra check, just in case we manage to call GetNewId() twice before enough ticks have passed to increment the sequence 
        lock (Lock)
        {
            if (sequencePart <= _lastSequencePart)
                sequencePart = _lastSequencePart + 1;

            _lastSequencePart = sequencePart;
        }

        // shift so that the sequence part fills the most significant 6 bytes of the result value
        sequencePart = (sequencePart << 16);

        // randomize the lowest 2 bytes of the result, just in case two different client PCs call GetNewId() at exactly the same time
        var randomPart = Random.Next() & 0xFFFF;

        return sequencePart + randomPart;
    }

    // used if you want to generate an Id value for a historic time point (within the start and end dates)
    // there are no checks, compared to calls to GetNewId(), but the chances of colliding values are still almost zero
    public static long GetIdForDateTime(DateTime dt)
    {
        if (dt < PeriodStartDate || dt > PeriodStartDate)
            throw new ArgumentException($"value must be in the range {PeriodStartDate:dd MMM yyyy} - {PeriodEndDate:dd MMM yyyy}");

        var sequencePart = GetSequenceValueForDateTime(dt.ToUniversalTime());
        var randomPart = Random.Next() & 0xFFFF;
        return ( sequencePart << 16 ) + randomPart;
    }

    // Get a 6 byte sequence value from the specified date time - startDate => 0 --> endDate => 0x7FFFFFFFFFFF
    // For a 100 year time period, 1 unit of the sequence corresponds to about 0.022 ms
    private static long GetSequenceValueForDateTime(DateTime dt)
    {
        var ticksFromStart = dt.ToUniversalTime().Ticks - PeriodStartTicks;
        var proportionOfPeriod = (decimal)ticksFromStart / TotalPeriodTicks;
        var result = proportionOfPeriod * SEQUENCE_PART_PERMUTATIONS;
        return (long)result;
    }

    public static DateTime GetDateTimeForId(long value)
    {
        // strip off the random part - the two lowest bytes
        var timePart = value >> 16;
        var proportionOfTotalPeriod = (decimal) timePart / SEQUENCE_PART_PERMUTATIONS;
        var ticks = (long)(proportionOfTotalPeriod * TotalPeriodTicks);
        var result = PeriodStartDate.AddTicks(ticks);
        return result;
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.