क्या सभी कॉलमों को चिह्नित करना उचित है लेकिन प्राथमिक कुंजी के रूप में एक?


9

मेरे पास फिल्मों का प्रतिनिधित्व करने वाली एक टेबल है। क्षेत्र हैं:
id (PK), title, genre, runtime, released_in, tags, origin, downloads

मेरे डेटाबेस को डुप्लिकेट पंक्तियों द्वारा प्रदूषित नहीं किया जा सकता है, इसलिए मैं विशिष्टता को लागू करना चाहता हूं। समस्या यह है कि अलग-अलग फिल्मों में एक ही शीर्षक हो सकता है, या एक ही क्षेत्र को छोड़कर tagsऔर downloads। विशिष्टता कैसे लागू करें?

मैंने दो तरीके से सोचा:

  • downloadsप्राथमिक कुंजी को छोड़कर सभी फ़ील्ड बनाएं । मैं downloadsJSON के बाद से बाहर रख रहा हूं और यह संभवतः प्रदर्शन को प्रभावित करेगा।
  • केवल idप्राथमिक कुंजी के रूप में रखें, लेकिन अन्य सभी स्तंभों (छोड़कर, फिर से downloads) के साथ एक अद्वितीय बाधा जोड़ें ।

मैंने यह प्रश्न पढ़ा जो बहुत समान है, लेकिन मुझे यह समझ में नहीं आया कि मुझे क्या करना चाहिए। वर्तमान में यह तालिका किसी अन्य तालिका से संबंधित नहीं है, लेकिन भविष्य में हो सकती है।

फिलहाल मेरे पास 20,000 से कम रिकॉर्ड हैं, लेकिन मुझे उम्मीद है कि संख्या बढ़ेगी। मुझे नहीं पता कि यह मुद्दे के लिए कुछ प्रासंगिक है।

संपादित करें: मैंने स्कीमा को संशोधित किया है और यहां बताया गया है कि मैं तालिका कैसे बनाऊंगा:

CREATE TABLE movies (
    id          serial PRIMARY KEY,
    title       text NOT NULL,
    runtime     smallint NOT NULL CHECK (runtime >= 0),
    released_in smallint NOT NULL CHECK (released_in > 0),
    genres      text[] NOT NULL default ARRAY[]::text[],
    tags        text[] NOT NULL default ARRAY[]::text[],
    origin      text[] NOT NULL default ARRAY[]::text[],
    downloads   json NOT NULL,
    inserted_at timestamp NOT NULL default current_timestamp,
    CONSTRAINT must_be_unique UNIQUE(title,runtime,released_in,genres,tags,origin)
);

मैंने timestampकॉलम भी जोड़ा , लेकिन यह कोई समस्या नहीं है क्योंकि मैं इसे नहीं छूऊंगा। तो यह हमेशा स्वचालित और अद्वितीय होगा।


एसओ पर बारीकी से संबंधित प्रश्न (उत्तर के साथ): क्या मुझे अपनी मेज के लिए एक प्राथमिक कुंजी की आवश्यकता है, जिसमें एक UNIQUE (समग्र 4-कॉलम) हो, जिनमें से एक NULL हो सकता है? । यदि कोई कॉलम NULL हो सकता है, तो तुरंत इस पर विचार करें: dba.stackexchange.com/q/9759/3684
एरविन ब्रान्डस्टेट्टर

जवाबों:


4

अब आपकी तालिका की परिभाषा उचित है। सभी स्तंभों NOT NULLके साथ UNIQUEबाधा उम्मीद के मुताबिक काम करेगी - वर्तनी में टाइपो और मामूली अंतरों को छोड़कर, जो कि सामान्य हो सकती है मुझे डर है। @ A_horse की टिप्पणी पर विचार करें ।

कार्यात्मक अद्वितीय सूचकांक के साथ वैकल्पिक

अन्य विकल्प एक कार्यात्मक अद्वितीय सूचकांक होगा (जो @ टिप्पणी के समान है )। लेकिन मैं uuidसूचकांक आकार और प्रदर्शन को अनुकूलित करने के लिए एक डेटा प्रकार का उपयोग करूंगा ।

सरणी से पाठ तक नहीं है IMMUTABLE(इसके सामान्य कार्यान्वयन के कारण):

इसलिए आपको इसे अपरिवर्तनीय घोषित करने के लिए एक छोटे सहायक की आवश्यकता है :

CREATE OR REPLACE FUNCTION f_movie_uuid(_title text
                                      , _runtime int2
                                      , _released_in int2
                                      , _genres text[]
                                      , _tags text[]
                                      , _origin text[])
  RETURNS uuid LANGUAGE sql IMMUTABLE AS  -- faking IMMUTABLE
'SELECT md5(_title || _runtime::text || _released_in::text
         || _genres::text || _tags::text || _origin::text)::uuid';

सूचकांक परिभाषा के लिए इसका उपयोग करें:

CREATE UNIQUE INDEX movies_uni_idx
ON movies (f_movie_uuid(title,runtime,released_in,genres,tags,origin));

एसक्यूएल फिडल।

अधिक जानकारी:

आप पीके के रूप में उत्पन्न यूयूआईडी का उपयोग कर सकते हैं, लेकिन मैं अभी भी serialअपने 4 बाइट्स के साथ कॉलम का उपयोग करूंगा , जो एफके संदर्भों और अन्य उद्देश्यों के लिए सरल और सस्ता है। एक UUID वितरित प्रणालियों के लिए एक बढ़िया विकल्प होगा, जिन्हें स्वतंत्र रूप से PK मान उत्पन्न करने की आवश्यकता होती है। या बहुत बड़ी तालिकाओं के लिए, लेकिन उसके लिए हमारे सौर मंडल में लगभग पर्याप्त फिल्में नहीं हैं।

फायदा और नुकसान

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

अन्य विशिष्ट लाभ हैं, यहां एक सूची है:

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

सभी कॉलमों को आपस में जोड़कर झूठी सकारात्मकता का परिचय दिया जा सकता है ( 'foo ' || 'bar' = 'foob ' || 'ar'लेकिन यह इस मामले के लिए बहुत संभावना नहीं है। टाइपोस की संभावना बहुत अधिक है कि आप इसे यहां सुरक्षित रूप से अनदेखा कर सकते हैं।

विशिष्टता और सरणियाँ

ऑपरेटर पर निर्भर किसी भी अनूठी व्यवस्था में समझ बनाने के लिए एरर्स को लगातार क्रमबद्ध करना होगा । मैं के लिए लुक-अप टेबल सुझाव है , और साथ पी और अद्वितीय प्रविष्टियों, जो सरणी तत्वों के लिए फजी खोज अनुमति देते हैं। फिर:='{1,2}' <> '{2,1}'genretagoriginserial

किसी भी तरह से, सीधे सरणियों के साथ काम करना या सामान्यीकृत स्कीमा और एक भौतिक दृष्टिकोण के साथ, सही सूचकांक और ऑपरेटरों के साथ खोज करना बहुत कुशल हो सकता है:

अलग

यदि आप Postgres का उपयोग कर रहे हैं 9.4 या बाद में jsonbइसके बजाय परjson विचार करें ।


6

कल्पना कीजिए कि आप दोस्तों के एक समूह के साथ बाहर हैं और बातचीत फिल्मों में बदल जाती है। कोई पूछता है, "आपने थ्री मस्किटर्स के बारे में क्या सोचा?" आप जवाब देते हैं, "कौन सा?"

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

मेरे सवाल का जवाब और आपका वही है।

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

यहां तक ​​कि रनटाइम्स भी अलग-अलग हो सकती हैं, खासकर थिएटर और वीसीआर / डीवीडी / बी-रे संस्करणों के बीच।

इसलिए आपको कठिन, वस्तुनिष्ठ विशेषताओं की आवश्यकता है जो एक मीडिया रिलीज़ से दूसरे में नहीं बदलेगी। दुर्भाग्य से, यह फिल्म के नाम को बाहर कर सकता है क्योंकि फिल्मों का नाम बदला जाना माना जाता है, खासकर एक सीक्वल की रिलीज के बाद।

रिलीज की तारीख के बारे में क्या? 1993 की नाटकीय रिलीज़? 1999 का वीसीआर रिलीज़? 2004 की डीवीडी रिलीज़? तुम्हें नया तरीका मिल गया है।

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

हम्म, मैं बेहतर रोकूँगा, जबकि अभी भी कुछ मापदंड बाकी हैं।

कुछ अतिरिक्त बिंदु:

  • हां, सरोगेट कुंजी रखें और प्राकृतिक कुंजी क्षेत्रों पर एक अद्वितीय सूचकांक बनाएं (यदि आप अंततः उन नीचे कील कर सकते हैं)। सरोगेट कुंजी विदेशी कुंजी संदर्भों के लिए सबसे अच्छा है। आप हर तालिका में सभी प्राकृतिक कुंजी फ़ील्ड को डुप्लिकेट नहीं करना चाहते हैं जिसमें किसी फिल्म का संदर्भ होता है।
  • सरणी फ़ील्ड (जीन, टैग, उत्पत्ति) छोड़ें। आगे बढ़ें और उन विशेषताओं को ठीक से सामान्य करें। मैंने कभी भी ऐसा एरे फ़ील्ड नहीं देखा है जो बहुत अधिक परेशानी का विषय नहीं था, बल्कि इससे भी अधिक परेशानी की बात थी, खासकर यदि आप चाहते हैं कि वे खोजा जा सके ("... जहाँ शैली = 'डरावनी' ...")। ध्यान दें कि यह स्वचालित रूप से मामले के अंतर और वर्तनी ("साइंस फिक्शन" बनाम "SciFi") के साथ किसी भी मुद्दे को समाप्त नहीं करेगा - जब तक आप लुकअप तालिकाओं को ठीक से बनाए नहीं रखते । लेकिन एक बड़ी तालिका की हर पंक्ति के प्रत्येक सरणी सेल की तुलना में एक छोटी तालिका के एक क्षेत्र में इस तरह के अंतर की जांच करना बहुत आसान है।

4

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


1
यदि व्यावसायिक नियम कहते हैं कि FOO और BAR में मूल्यों का संयोजन अद्वितीय होना चाहिए, तो एक आईडी जोड़ने से वह हासिल नहीं होने वाला है। आईडी जोड़ने से सिर्फ FOO और BAR को शामिल करने से बचने की सुविधा मिलती है जैसे कि संदर्भ तालिका में। जो बदले में अधिक जुड़ाव की आवश्यकता होती है क्योंकि FOO और BAR विशेषताएँ (जो बिज़नेस आइडेंटिफ़ायर ले जाती हैं) वे नहीं हैं जहाँ वे हो सकते थे (और जहाँ वे होने की संभावना है, कम से कम व्यावसायिक दृष्टिकोण से)।
इरविन स्मौट

1
यह "पंक्तियाँ" नहीं है जो अद्वितीय होनी चाहिए, यह वही है जो व्यवसाय कहता है कि उनके पहचानकर्ता हैं जो होना चाहिए। यदि वह गुण FOO और BAR का संयोजन है, तो यह गुण FOO और BAR का संयोजन है।
इरविन स्मौट

2
आईडी होने या न होने से आपकी तालिका में "व्यवसाय" कॉलम की विशिष्टता के प्रवर्तन की कोई समस्या हल नहीं होती है। उपयुक्त कुंजियों को घोषित करके विशिष्टता का प्रवर्तन किया जाना चाहिए (जो आप करते हैं - तथ्य यह है कि आपने "कुंजी" के बजाय वाक्य रचना शब्द "CONSTRAINT" का उपयोग किया है इसका मतलब यह नहीं है कि यह एक कुंजी नहीं है)।
इरविन स्मौट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.