NVARCHAR स्तंभ प्राथमिक कुंजी के रूप में या अद्वितीय स्तंभ के रूप में


11

मैं SQL सर्वर 2012 डेटाबेस विकसित कर रहा हूं और मुझे प्राथमिक कुंजियों के रूप में nvarchar कॉलम के बारे में संदेह है।

मेरे पास यह तालिका है:

CREATE TABLE [dbo].[CODES]
(
    [ID_CODE] [bigint] IDENTITY(1,1) NOT NULL,
    [CODE_LEVEL] [tinyint] NOT NULL,
    [CODE] [nvarchar](20) NOT NULL,
    [FLAG] [tinyint] NOT NULL,
    [IS_TRANSMITTED] [bit] NOT NULL DEFAULT 0,
     CONSTRAINT [PK_CODES] PRIMARY KEY CLUSTERED 
    (
        [CODE_LEVEL] ASC,
        [CODE] ASC
    )
)

लेकिन अब मैं [CODE]कॉलम को प्राथमिक कुंजी के रूप में उपयोग करना चाहता हूं और [ID_CODE]कॉलम को हटाता हूं ।

यदि मेरे पास कोई NVARCHARकॉलम है तो क्या कोई समस्या या जुर्माना है PRIMARY KEY?

[CODE]स्तंभ मान अद्वितीय होना चाहिए, इसलिए मैंने सोचा है कि मैं UNIQUEउस स्तंभ पर एक बाधा निर्धारित कर सकता हूं ।

क्या मुझे [CODE]प्राथमिक कुंजी के रूप में उपयोग करना है या यह बेहतर है यदि मैं स्तंभ UNIQUEपर एक बाधा निर्धारित करता हूं [CODE]?


1
विचार करने में काफी महत्वपूर्ण बात यह है कि आपकी तालिका में कितनी पंक्तियाँ होंगी?
जेम्स ज़ेड

यह प्रति उत्तर नहीं है , लेकिन मुझे लगता है कि आपका CODEकॉलम अद्वितीय होना चाहिए, लेकिन प्राथमिक कुंजी नहीं है। मुझे संदेह है कि यह जानकारी लेती है। यदि वह जानकारी किसी भी तरह से परिवर्तनशील है, तो आपका CODEपरिवर्तन होना चाहिए या पुराना हो जाना चाहिए। यह आपकी प्राथमिक कुंजी को अस्थिर बना देगा, और मैं इसे अच्छी तरह से समाप्त नहीं देख सकता। अपने पीके को बस एक कुंजी बनाने के लिए सबसे अच्छा है, और आपका CODE वही कर सकता है जो उसे पसंद है। बस एक राय है।
मन्नंगो

@ मानगो, आपकी टिप्पणी के लिए धन्यवाद। हां, मैंने ऐसा किया है: ID_CODE प्राथमिक कुंजी है और CODE UNIQUE है।
VansFannel

जवाबों:


13

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

आपको यह विचार करने की आवश्यकता है कि एक क्लस्टर इंडेक्स में फ़ील्ड को गैर-क्लस्टर इंडेक्स पर ले जाया जाता है। तो आप प्रति पंक्ति केवल 40 बाइट्स तक नहीं देख रहे हैं, लेकिन (40 * some_number) बाइट्स। और किसी भी FK तालिकाओं में आपके पास वही 40 बाइट पंक्ति में हैं और अधिक से अधिक बार उस क्षेत्र पर एक गैर-क्लस्टर इंडेक्स नहीं होगा जैसा कि JOINs में उपयोग किया जा रहा है, इसलिए अब यह वास्तव में किसी भी तालिकाओं में दोगुना है कि FK यह वाला। यदि किसी को यह सोचने की इच्छा है कि 40 बाइट्स * 1 मिलियन पंक्तियाँ * इसकी 10 प्रतियों के बारे में चिंतित होने की कोई बात नहीं है, तो कृपया मेरा लेख देखें डिस्क सस्ता है! औरली? इस निर्णय से प्रभावित क्षेत्रों के सभी (या कम से कम अधिकांश) विवरण।

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

इसलिए, कुछ का उपयोग CHAR(5)करना संभवत: क्लस्टर पीके के लिए ठीक होगा, लेकिन ज्यादातर अगर यह भी परिभाषित किया गया था COLLATE Latin1_General_100_BIN2(या ऐसा कुछ)।

और क्या [CODE]कभी भी मूल्य बदल सकता है? यदि हाँ, तो इसका एक और कारण यह भी है कि इसे पीके के रूप में उपयोग न करें (भले ही आप एफके सेट करते हैं ON UPDATE CASCADE)। अगर यह ठीक है या नहीं बदल सकता है, लेकिन अभी भी पर्याप्त कारण से अधिक है पहले से ही इसे एक संकुल पीके के रूप में उपयोग नहीं करते हैं।

बेशक, सवाल गलत तरीके से व्यक्त किया जा सकता है क्योंकि ऐसा लगता है कि आपके पास पहले से ही आपके पीके में यह फ़ील्ड है।

भले ही, आपका सबसे अच्छा विकल्प, अब तक, [ID_CODE]क्लस्टर्ड पीके के रूप में उपयोग करना है, एफके के रूप में संबंधित तालिकाओं में उस फ़ील्ड का उपयोग करें और [CODE]एक के रूप में रखें UNIQUE INDEX(जिसका अर्थ है कि यह "वैकल्पिक कुंजी" है)।


अद्यतन
इस उत्तर पर एक टिप्पणी में इस सवाल पर आधारित एक और अधिक जानकारी:

क्या [ID_CODE], प्राथमिक कुंजी के रूप में, सबसे अच्छा विकल्प है अगर मैं तालिका देखने के लिए [CODE] कॉलम का उपयोग करता हूं?

यह सब एक महान कई कारकों पर निर्भर करता है, जिनमें से कुछ मैं पहले ही उल्लेख कर चुका हूं, लेकिन आराम करेंगे:

एक प्राथमिक कुंजी यह है कि व्यक्तिगत पंक्ति को कैसे पहचाना जाता है, किसी विदेशी कुंजी द्वारा संदर्भित किया जाता है या नहीं। आपकी प्रणाली आंतरिक रूप से कैसे पहचानती है कि पंक्ति किससे संबंधित है, लेकिन यह आवश्यक नहीं है कि कैसे, आपके उपयोगकर्ता स्वयं या उस पंक्ति को कैसे पहचानें। अद्वितीय डेटा वाला कोई भी NULL कॉलम काम नहीं कर सकता है , लेकिन विचार करने के लिए व्यावहारिकता के मुद्दे हैं, खासकर यदि पीके वास्तव में, किसी भी एफके द्वारा संदर्भित है। उदाहरण के लिए GUID अनूठे हैं और कुछ लोग वास्तव में विभिन्न कारणों से उनका उपयोग करना पसंद करते हैं, लेकिन वे Clustered Indexes के लिए काफी खराब हैं ( NEWSEQUENTIALIDबेहतर है, लेकिन सही नहीं है)। दूसरी ओर, GUIDs वैकल्पिक कुंजियों के रूप में ठीक हैं और पंक्ति को देखने के लिए ऐप द्वारा उपयोग किया जाता है, लेकिन JOIN अभी भी एक INT (या समान) पीके का उपयोग करके किया जाता है।

अब तक आपने हमें यह नहीं बताया कि यह [CODE]क्षेत्र सभी कोणों से सिस्टम में कैसे फिट बैठता है, अब इस बात का उल्लेख करते हुए कि यह कैसे आप पंक्तियों को देखते हैं, लेकिन क्या यह सभी प्रश्नों के लिए है या सिर्फ कुछ के लिए है? इसलिये:

  • [CODE]मूल्य के बारे में :

    • यह कैसे उत्पन्न होता है?
    • क्या यह वृद्धिशील या पीडो-यादृच्छिक है?
    • क्या यह एक समान लंबाई या भिन्न लंबाई है?
    • क्या वर्ण उपयोग किया जाता है?
    • यदि वर्णमाला वर्णों का उपयोग कर रहे हैं: क्या यह मामला-संवेदनशील या असंवेदनशील है?
    • डालने के बाद क्या यह कभी बदल सकता है?
  • इस तालिका के बारे में:

    • इस तालिका में कोई अन्य तालिका FK करें? या ये फ़ील्ड ( [CODE]या [ID_CODE]) अन्य तालिकाओं में उपयोग की जाती हैं, भले ही स्पष्ट रूप से विदेशी कुंजी न हो?
    • यदि [CODE] व्यक्तिगत पंक्तियों को प्राप्त करने के लिए एकमात्र फ़ील्ड का उपयोग किया जाता है, तो [ID_CODE]फ़ील्ड किस उद्देश्य से कार्य करता है ? यदि इसका उपयोग नहीं किया जाता है, तो पहले स्थान पर क्यों है (जो "क्या [CODE]कभी क्षेत्र बदल सकता है?") के उत्तर पर निर्भर हो सकता है ।
    • इस तालिका में कितनी पंक्तियाँ हैं?
    • यदि अन्य तालिकाएँ इस तालिका को संदर्भित करती हैं, तो उनमें से प्रत्येक में कितनी और कितनी पंक्तियाँ हैं?
    • इस तालिका के सूचकांक क्या हैं?

यह निर्णय "NVARCHAR हाँ या नहीं?" के सवाल पर विशुद्ध रूप से नहीं किया जा सकता है। मैं फिर से कहूंगा कि आम तौर पर बोलना मुझे एक अच्छा विचार नहीं लगता है, लेकिन निश्चित रूप से ऐसे समय होते हैं जब यह ठीक होता है। इस तालिका में इतने कम क्षेत्रों को देखते हुए यह संभावना नहीं है कि कोई और अधिक है, या कम से कम कई नहीं, अनुक्रमणिका हैं। तो आप [CODE]क्लस्टर्ड इंडेक्स के रूप में ठीक हो सकते हैं । और अगर कोई अन्य तालिका इस तालिका का संदर्भ नहीं देती है, तो आप इसे पीके बना सकते हैं। लेकिन, अगर अन्य टेबल इस तालिका को संदर्भित करते हैं तो मैं [ID_CODE]पीके के रूप में क्षेत्र का विकल्प चुनूंगा, भले ही गैर-क्लस्टर हो।


क्या अनाम downvoter (जो डाउन-वोटेड @noIDonthissystem का जवाब भी देता है) किसी भी रचनात्मक आलोचना की पेशकश करने या कुछ त्रुटिपूर्ण तर्क देने की परवाह करता है?
सोलोमन रटज़की

आपके उत्तर के लिए धन्यवाद। क्या [ID_CODE], PRIMARY KEYअगर मैं [CODE]तालिका देखने के लिए कॉलम का उपयोग करता हूं तो सबसे अच्छा विकल्प है ?
VansFannel

@VansFannel कृपया मेरा अपडेट देखें। धन्यवाद।
सोलोमन रटज़की 16

मैं इस dba समुदाय में शामिल हो गया बस इस उत्तर को बढ़ा दूंगा।
अहमत अर्सलान

6

आपको अवधारणाओं को अलग करना होगा:

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

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

प्राथमिक कुंजी के लिए क्लस्टर इंडेक्स होना आवश्यक नहीं है। आप के ID_CODEरूप में पीके और (CODE_LEVEL, CODE)संकुल कुंजी के रूप में हो सकता है । या फिर इसके विपरीत।

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

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

प्राथमिक कुंजी विकल्प के रूप में, यह भी एक मुद्दा नहीं होना चाहिए: आपका डेटा मॉडल, आपका ऐप लॉजिक, प्राथमिक कुंजी क्या होना चाहिए यह निर्धारित करना चाहिए।

कहा जा रहा है, मेरे 2c: NVARCHAR(20)है विस्तृत। एक बड़ी तालिका के लिए भी पूरी तरह से स्वीकार्य क्लस्टर आकार है।


आपके उत्तर के लिए धन्यवाद। क्या [ID_CODE], PRIMARY KEYयदि मैं तालिका देखने के लिए [CODE]कॉलम (और शायद [CODE_LEVEL]) का उपयोग करता हूं, तो सबसे अच्छा विकल्प है ?
VansFannel

@VansFannel केवल आप ही इसका उत्तर दे सकते हैं।
रेमस रुसानु

लेकिन आपकी राय में ...
VansFannel

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

धन्यवाद। मैं [CODE]कॉलम को PRIMARY KEY की तरह इस्तेमाल करूंगा ।
वंसफैननेल

4

मैं nvarchar(20)अपने डेटाबेस में किसी को भी पीके बनने की अनुमति नहीं दूंगा। आप डिस्क स्थान और कैश मेमोरी बर्बाद करते हैं। इस तालिका का प्रत्येक सूचकांक और इसके लिए सभी FK इस विस्तृत मूल्य की प्रतिकृति बनाते हैं। शायद एक चर (20) अगर वे इसे सही ठहरा सकते हैं। आप किस तरह का डेटा स्टोर करने की कोशिश कर रहे हैं CODE? क्या आपको वास्तव में nvarchar वर्णों को संग्रहीत करने की आवश्यकता है? मैं पीके "आंतरिक" मूल्यों को उपयोगकर्ताओं द्वारा नहीं देखा जाता हूं, और मैं उन मूल्यों को रखने की कोशिश करता हूं जो अलग-अलग प्रदर्शित होते हैं। प्रदर्शित मूल्यों को कभी-कभी बदलने की आवश्यकता होती है, जो पीके + एफके के साथ बहुत समस्याग्रस्त हो जाता है।

इसके अलावा, क्या आपको पता है कि 'बिगिन्ट आइडेंटिटी (1,1)' 9,223,372,036,854,775,807 तक बढ़ सकता है?

[ID_CODE] [bigint] IDENTITY(1,1)

जब तक आप Google के लिए इस डेटाबेस का निर्माण कर रहे हैं, तब तक int identity (1,1)इसकी 2 बिलियन की सीमा पर्याप्त नहीं होगी?


int SQL में 4 बाइट है, जो आपको -2.1Billion से + 2.1Billion देता है।
डेटागोड

@ दत्तागोड, हा धन्यवाद, इतने अंक मैंने गलत गिने!
इस सिस्टम पर कोई आईडी

आपके उत्तर के लिए धन्यवाद। क्या [ID_CODE], PRIMARY KEYअगर मैं [CODE]तालिका देखने के लिए कॉलम का उपयोग करता हूं तो सबसे अच्छा विकल्प है ? धन्यवाद।
VansFannel

मैं इस नाव में तब तक रहा करता था जब तक कि किसी ने मेरे DB में डेटा / उपयोगकर्ताओं की भविष्यवाणी करने के लिए "int" की अनुक्रमिक प्रकृति का उपयोग नहीं किया था और मेरे पास सबसे अधिक सब कुछ काटा। फिर कभी नहीं। डीबी का सामना करने वाली जनता को जानकारी प्राप्त करने के लिए थोड़ा और मुश्किल होने की आवश्यकता है।
DaBlue

3

यदि आप जागरूक नहीं हैं तो nvarchar / varchar का उपयोग करते समय व्यापक कुंजियों का उपयोग करने के अलावा आपके पास कोई अंतर्निहित / ध्यान देने योग्य जुर्माना नहीं होना चाहिए। खासकर यदि आप उन्हें समग्र कुंजियों में संयोजित करना शुरू करते हैं।

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

हालांकि, आपको यह विचार करना चाहिए कि क्या आप वास्तव में इसे प्राथमिक कुंजी के रूप में चाहते हैं या सिर्फ एक अद्वितीय (क्लस्टर) सूचकांक। क्लस्टर इंडेक्स और प्राथमिक कुंजी (मूल रूप से - प्राथमिक कुंजी आपके डेटा की पहचान करता है, लेकिन इंडेक्स आप डेटा क्वेरी कैसे करते हैं) के बीच एक छोटा (छोटा) अंतर होता है, इसलिए यदि आप चाहें तो आप आसानी से अपनी आईडी_कोड को एक प्राथमिक कुंजी और केवल बना सकते हैं CODE पर एक अद्वितीय क्लस्टर इंडेक्स बनाएं। (सूचना: SQL सर्वर स्वचालित रूप से आपकी प्राथमिक कुंजी को क्लस्टर इंडेक्स में बना देगा, जब तक कि आपने मैन्युअल रूप से क्लस्टर इंडेक्स स्वयं नहीं बनाया है)

यह भी विचार करें कि क्या आपको वास्तव में ID_Code की आवश्यकता है, आपके पास एक अद्वितीय कोड है।


2
वास्तव में, NVARCHAR(20)है 40 आकार (अधिकतम) में बाइट्स, और के बाद से यह के चर लंबाई स्तंभ, यह वास्तव में संकुल अनुक्रमणिका के लिए सबसे अच्छा विकल्प नहीं है। ID_CODEएक BIGINT IDENTITYहोना यहाँ बहुत बेहतर विकल्प होगा!
marc_s

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

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