आपको विदेशी कुंजियों को कहां परिभाषित करना चाहिए?


जवाबों:


41

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

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

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

विदेशी चाबियों के अन्य लाभ भी बहुत हैं। सभी का पक्ष लें - डेटाबेस पर FK डालें।


15

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

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


12

मैं पूरी तरह से डाउन-वोट करने की उम्मीद कर रहा हूं, क्योंकि यह एक डीबीए-केंद्रित समूह है।

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

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

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

कहा जा रहा है, कोई भी फेसबुक के रूप में शुरू नहीं करता है। अपने डेटाबेस में विदेशी कुंजियों को परिभाषित करके शुरू करें। पर नज़र रखें। यदि आपको समस्याएँ खत्म होती हैं, तो समझें कि आपको उन कुछ बाधाओं को छोड़ने की आवश्यकता हो सकती है।

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

अब मैं अपने लौ-मंदक सूट के साथ जाने जा रहा हूं।

EDIT 2012-03-23 ​​7:00 पूर्वाह्न

विदेशी कुंजियों के लॉकिंग परिणामों के बारे में सोचने पर, मैंने सर्वर लोड को जोड़कर आंतरिक रूप से उत्पन्न सभी अतिरिक्त पंक्ति लुकअप की लागत का उल्लेख करने की उपेक्षा की।

अंतत: मेरी बात यह है कि विदेशी कुंजियाँ स्वतंत्र नहीं हैं। कई मामलों में, लागत इसके लायक है, लेकिन ऐसे परिदृश्य हैं जहां लागत उनके लाभ से अधिक है।

EDIT 2012-03-23 ​​7:38 पूर्वाह्न

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

माता-पिता को संदर्भित करने वाली एक विदेशी कुंजी के साथ एक बाल तालिका पर विचार करें। एक उदाहरण के रूप में, MySQL में sakila नमूना डेटाबेस में फिल्म और film_actor टेबल देखें:

CREATE TABLE `film` (
  `film_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `description` text,
  `release_year` year(4) DEFAULT NULL,
  `language_id` tinyint(3) unsigned NOT NULL,
  `original_language_id` tinyint(3) unsigned DEFAULT NULL,
  `rental_duration` tinyint(3) unsigned NOT NULL DEFAULT '3',
  `rental_rate` decimal(4,2) NOT NULL DEFAULT '4.99',
  `length` smallint(5) unsigned DEFAULT NULL,
  `replacement_cost` decimal(5,2) NOT NULL DEFAULT '19.99',
  `rating` enum('G','PG','PG-13','R','NC-17') DEFAULT 'G',
  `special_features` set('Trailers','Commentaries','Deleted Scenes','Behind the Scenes') DEFAULT NULL,
  `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`film_id`),
  KEY `idx_title` (`title`),
  KEY `idx_fk_language_id` (`language_id`),
  KEY `idx_fk_original_language_id` (`original_language_id`),
  CONSTRAINT `fk_film_language` FOREIGN KEY (`language_id`) REFERENCES `language` (`language_id`) ON UPDATE CASCADE,
  CONSTRAINT `fk_film_language_original` FOREIGN KEY (`original_language_id`) REFERENCES `language` (`language_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8

CREATE TABLE `film_actor` (
  `actor_id` smallint(5) unsigned NOT NULL,
  `film_id` smallint(5) unsigned NOT NULL,
  `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`actor_id`,`film_id`),
  KEY `idx_fk_film_id` (`film_id`),
  CONSTRAINT `fk_film_actor_actor` FOREIGN KEY (`actor_id`) REFERENCES `actor` (`actor_id`) ON UPDATE CASCADE,
  CONSTRAINT `fk_film_actor_film` FOREIGN KEY (`film_id`) REFERENCES `film` (`film_id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8

प्रासंगिक बाधा मेरे उदाहरण के लिए film_actor (fk_film_actor_film) है।

session1> BEGIN;
session1> INSERT INTO film_actor (actor_id, film_id) VALUES (156, 508);
Query OK, 1 row affected (0.00 sec)

session2> BEGIN;
session2> UPDATE film SET release_year = 2005 WHERE film_id = 508;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

ध्यान दें कि मैं चाइल्ड टेबल में डालने के दौरान पेरेंट रो में एक असंबंधित फ़ील्ड को अपडेट करने में असमर्थ था। ऐसा इसलिए होता है क्योंकि InnoDB उस पंक्ति पर एक साझा लॉक रखता है जहाँ film.actil_for पर FK की कमी के कारण film.film_id = 508 है, इस प्रकार उस पंक्ति के लिए अद्यतन को आवश्यक लॉक प्राप्त नहीं हो सकता है। यदि आप उस ऑपरेशन को उल्टा करते हैं और पहले अद्यतन चलाते हैं, तो आपके पास एक ही व्यवहार है, लेकिन INSERT अवरुद्ध है।

session1> BEGIN;
session1> UPDATE film SET release_year = 2005 WHERE film_id = 508;
Query OK, 1 row affected (0.00 sec)

session2> BEGIN;
session2> INSERT INTO film_actor (actor_id, film_id) VALUES (156, 508);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

usersएक वेब अनुप्रयोग में एक तालिका पर विचार करें जहां अक्सर संबंधित तालिकाओं के दर्जनों होते हैं। किसी भी संबंधित पंक्ति पर अनिवार्य रूप से किसी भी ऑपरेशन को मूल पंक्ति को अद्यतन करने से रोकता है। जब आपके पास कई विदेशी कुंजी संबंध और बहुत अधिक संगामना हो तो यह एक चुनौतीपूर्ण समस्या हो सकती है।

FK बाधाओं के रूप में अच्छी तरह से चुनौतीपूर्ण टेबल रखरखाव के लिए workarounds बना सकते हैं। Percona से पीटर ज़ैतसेव के पास इस बारे में एक ब्लॉग पोस्ट है जो मुझे इससे बेहतर समझा सकता है: हाइजैकिंग इनोडब फॉरेन कीज़


टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
पॉल व्हाइट GoFundMonica कहते

6

डेटाबेस में विदेशी कुंजी का उपयोग करना अच्छा अभ्यास है। यह मदद करता है-

  • अवांछित डेटा की संभावना को हटाकर डेटा अखंडता बनाए रखने के लिए
  • प्रदर्शन बढ़ाने के लिए। उन प्रणालियों में जो ऑटो इंडेक्स फ़ील्ड, विदेशी प्रमुख संदर्भ प्रदर्शन को बढ़ावा दे सकते हैं
  • प्रोग्रामर द्वारा कम कोड लिखने के लिए। जैसे, उपयोग करनाON DELETE CASCADE
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.