क्या मुझे पीके प्रयोजनों के लिए एक क्रॉस-रेफरेंस टेबल में एक ऑटो-इन्क्रीमेंट / पहचान क्षेत्र जोड़ना चाहिए?


9

मैं अपने SQL सर्वर-होस्ट DB के लिए निम्न क्रॉस-रेफरेंस टेबल जोड़ रहा हूं:

company_id bigint not null (FK)
org_path nvarchar (2048) not null

company_idक्षेत्र को संदर्भित करता है idएक और तालिका में क्षेत्र (जिसमें यह प्राथमिक कुंजी है)।

यह देखते हुए कि एक ही के साथ कई रिकॉर्ड भी हो सकते हैं company_id, किसी भी प्राथमिक कुंजी को दोनों क्षेत्रों का उपयोग करना होगा। हालाँकि, मैं दोनों फ़ील्ड का उपयोग करके एक कुंजी बनाने में असमर्थ हूं क्योंकि org_pathSQL सर्वर के लिए बहुत लंबा है।

जैसा कि org_path, यह एकमात्र तालिका है जिसमें यह मौजूद है। इस तालिका में क्वेरीज़ या तो सभी प्रविष्टियों या सभी org_pathप्रविष्टियों के लिए पूछ रही हैं company_id। या इसे किसी अन्य तरीके से रखने के लिए, यह संदिग्ध लग रहा है कि यह तालिका कभी भी इसके बारे में बताएगी org_path। इसके अलावा, यह संभावना नहीं है कि org_pathअद्यतन किया जाएगा, और अधिक संभावना डाला और - शायद ही कभी - नष्ट कर दिया।

मुझे उम्मीद है कि कुल पंक्तियों की संख्या कम हजारों में होगी।

इसके अलावा, इसका कारण यह nvarchar (2048)है कि मूल्य को तीसरे पक्ष के DB में नकल करना है। एक विशिष्ट उदाहरण कुछ इस तरह होगा

\Translation Providers\[customer name]\[order name]\

और नृतत्वशास्त्र हो सकते हैं।

तो मेरा सवाल यह है: क्या यह एक ऑटो-इन्क्रीमेंट idफ़ील्ड को जोड़ने के लिए अधिक कुशल होगा और company_idप्राथमिक कुंजी के रूप में संयोजन के साथ उपयोग करेगा, या क्या यह अनावश्यक ओवरहेड जोड़ देगा - और क्या यह तथ्य है कि company_idकिसी अन्य तालिका में प्राथमिक कुंजी है यहाँ प्रभाव?

जवाबों:


7

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

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

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


12

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

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

इसलिए, का मुख्य प्रश्न:

क्या यह एक ऑटो-इन्क्रीमेंट idफ़ील्ड को जोड़ने के लिए अधिक कुशल होगा और company_idप्राथमिक कुंजी के रूप में संयोजन के साथ उपयोग करेगा, या क्या यह अनावश्यक हेडहेड होगा

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

क्या एक IDENTITYस्तंभ जोड़ा जाना चाहिए या क्या यह अनावश्यक ओवरहेड होगा?

यदि आप एक INT IDENTITYकॉलम जोड़ते हैं और इसका उपयोग पीके बनाने के लिए करते हैं, तो मान लें कि यह एक क्लस्टर किया गया पीके होगा, जो हर पंक्ति में 4 बाइट जोड़ता है। यह कॉलम प्रश्नों में दिखाई और प्रयोग करने योग्य है। यह एक विदेशी कुंजी के रूप में अन्य तालिकाओं में जोड़ा जा सकता है, हालांकि इस विशेष मामले में ऐसा नहीं होगा।

यदि आप INT IDENTITYकॉलम नहीं जोड़ते हैं , तो आप इस तालिका पर PK नहीं बना सकते। हालाँकि, जब तक आप UNIQUEविकल्प का उपयोग नहीं करते तब तक आप टेबल पर एक संकुल सूचकांक बना सकते हैं । इस स्थिति में, SQL सर्वर एक छुपा स्तंभ जोड़ देगा जिसे "विशिष्ट" कहा जाता है जो ऊपर वर्णित अनुसार व्यवहार करता है। क्योंकि स्तंभ छिपा हुआ है, इसका उपयोग प्रश्नों में या विदेशी कुंजी के संदर्भ के रूप में नहीं किया जा सकता है।

जहाँ तक दक्षता जाती है, ये विकल्प लगभग समान होते हैं। हां, कुछ पंक्तियों (प्रारंभिक अद्वितीय कुंजी मानों वाले) को 0 बाइट्स लेने के कारण गैर-अद्वितीय क्लस्टर इंडेक्स होने से थोड़ा कम स्थान लिया जाएगा, जबकि IDENTITY/ PK में सभी पंक्तियों में 4 बाइट्स होंगे। लेकिन 0 बाइट पंक्तियों के लिए पर्याप्त नहीं होगा (विशेष रूप से अपेक्षित पंक्तियों की छोटी मात्रा के साथ) कभी अंतर पर ध्यान देने के लिए, अकेले IDप्रश्नों में कॉलम का उपयोग करने में सक्षम होने की सुविधा को बाहर करने दें।

INT आइडेंटिटी कॉलम या पर्सेंटेड org_pathकम्प्यूटेड कॉलम का हैश ?

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

प्रमुख स्तंभ आदेश

यह देखते हुए कि IDकॉलम शायद ही कभी, यदि कभी प्रश्नों में उपयोग किया जाता है, और यह देखते हुए कि दो मुख्य उपयोग-मामलों को "सभी पंक्तियों" या "दिए गए सभी पंक्तियों" को प्राप्त company_idकरना है, तो मैं पीके पर बनाऊंगा company_id, id। और इसका मतलब है कि पंक्तियों को क्रमिक रूप से नहीं डाला गया है, मैं FILLFACTOR90 की संख्या निर्दिष्ट करूंगा। विखंडन को कम करने के लिए आपको नियमित सूचकांक रखरखाव करने की भी आवश्यकता होगी।

दूसरा सवाल

तथ्य यह है कि company_id एक अन्य तालिका में प्राथमिक कुंजी है, यहां कोई प्रभाव नहीं है

नहीं।

उत्प्रेरक

चूँकि org_pathमूल्य एक company_idअद्वितीय हैं, इसलिए आपको इसे INSERT, UPDATEलागू करने के लिए एक ट्रिगर बनाना चाहिए । उत्प्रेरक में, एक कर IF EXISTSएक प्रश्न है कि शायद एक करता है के साथ COUNT(*)और GROUP BY company_id, org_path। यदि कुछ पाया जाता है, ROLLBACKतो डीएमएल ऑपरेशन को रद्द करने के लिए जारी करें और फिर एक RAISERRORकहावत है कि डुप्लिकेट हैं।

मिलान

मेरे प्रारंभिक उत्तर में (प्रश्न के मूल शब्दों / विरल विवरणों के आधार पर, और यहाँ संशोधन इतिहास में उपलब्ध है ), मैंने संभवतः एक बाइनरी (यानी _BIN2) कॉलेशन का उपयोग करने का सुझाव दिया था । अब जब हमारे पास अंतर्दृष्टि है कि वास्तव में क्या org_pathहै, तो मैं बाइनरी कोलेशन का उपयोग करने की सिफारिश नहीं करूंगा । चूँकि विशिष्ट अंक होंगे, आप भाषाई तुल्यता का उपयोग करना चाहते हैं।



0

आपको पीके की आवश्यकता क्यों है?

सिर्फ गैर-संकुल सूचकांक के रूप में company_id के साथ क्यों नहीं?

आपने कहा कि सभी प्रविष्टियाँ सभी प्रविष्टियों पर या company_id द्वारा हैं।
शायद ही कभी अद्यतन करें org_path को
हटाएं
, यह एकमात्र तालिका है जिसमें यह मौजूद है

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

यदि आप DRI के बारे में चिंतित हैं तो तालिकाओं को Company_id के लिए FK के रूप में कंपनी तालिका का उपयोग करना चाहिए


अरे। के बारे में " क्यों नहीं बस एक गैर संकुल अनुक्रमणिका के रूप में company_id साथ जाना? ": क्योंकि है कि 2 नीचे पक्षों के लिए होता है: 1) यह 1 और बात स्थान ले होगा, जबकि एक क्लस्टर सूचकांक है तालिका कोई अतिरिक्त आइटम हां, और 2) इसे अभी भी NVARCHAR फ़ील्ड प्राप्त करने के लिए एक RID लुकअप की आवश्यकता होगी, जब तक कि वह एक INCLUDEकॉलम न हो, लेकिन यह और भी बदतर है क्योंकि यह केवल तालिका को डुप्लिकेट कर रहा है। सच है, पीके आवश्यक नहीं है; महत्वपूर्ण हिस्सा क्लस्टर इंडेक्स है। लेकिन एक बार जब आपके पास पहचान हो जाती है, तो आप पीके के साथ जा सकते हैं। और कृपया मेरे उत्तर की नई कड़ी को यूनीकिफायर पर वॉक-थ्रू के लिए देखें R
सोलोमन रटज़की

@srzzky लेकिन यह एक 4 बाइट पूर्णांक यूनिफ़ायर से बचा जाता है, इसलिए मैं देखता हूं कि एक धोने के रूप में
paparazzo

10k से कम पंक्तियों के साथ, इससे कोई फर्क नहीं पड़ेगा; आपको शायद 4 पंक्तियों के प्रभाव को नोटिस करने से पहले लाखों पंक्तियों में होना चाहिए। तो "सभी पंक्तियों को प्राप्त करें" क्वेरी के लिए इनमें से किसी भी विकल्प में वास्तव में कोई अंतर नहीं है। लेकिन "company_id = @param" क्वेरी के लिए, company_id द्वारा भौतिक रूप से ऑर्डर किए गए डेटा को रखने में मदद मिलेगी, खासकर जब इसे हर पंक्ति के लिए RID लुकअप करने की आवश्यकता नहीं है।
सोलोमन रटज़की

@srzzky वॉश एक धो है - 10K या 1G। यह ओपी के लिए विचार करने के लिए कुछ है।
पापराज़ो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.