PostgreSQL में विरासत में मिली तालिकाओं का उपयोग कब करें?


84

किन स्थितियों में आपको विरासत में मिली तालिकाओं का उपयोग करना चाहिए? मैंने उन्हें बहुत संक्षेप में उपयोग करने की कोशिश की और विरासत OOP दुनिया में ऐसा नहीं लगता था।

मैंने सोचा कि यह इस तरह से काम करता है:

तालिका usersजिसमें सभी उपयोगकर्ता स्तरों के लिए आवश्यक सभी फ़ील्ड हैं। टेबल्स चाहते moderators, admins, bloggers, आदि लेकिन खेतों कर रहे हैं नहीं माता पिता से जाँच की। उदाहरण के लिए usersईमेल क्षेत्र है और विरासत bloggersमें मिला यह अब भी है लेकिन यह दोनों के लिए usersऔर bloggersएक ही समय में अद्वितीय नहीं है । अर्थात। उसी तरह मैं दोनों तालिकाओं में ईमेल फ़ील्ड जोड़ता हूं।

केवल उपयोग मैं के बारे में सोच सकता है क्षेत्रों है कि आमतौर पर की तरह, उपयोग किया जाता है row_is_deleted , created_at , modified_at । क्या यह विरासत में मिली तालिकाओं का एकमात्र उपयोग है?

जवाबों:


111

पोस्टग्रेज में टेबल इनहेरिटेंस का उपयोग करने के कुछ प्रमुख कारण हैं।

कहते हैं, हमारे पास आँकड़ों के लिए आवश्यक कुछ सारणियाँ हैं, जो हर महीने बनाई और भरी जाती हैं:

statistics
    - statistics_2010_04 (inherits statistics)
    - statistics_2010_05 (inherits statistics)

इस नमूने में, हमारे पास प्रत्येक तालिका में 2.000.000 पंक्तियाँ हैं। प्रत्येक तालिका में एक CHECK बाधा होती है, जिससे यह सुनिश्चित होता है कि मिलान वाले महीने का केवल डेटा इसमें संग्रहीत किया जाता है।

तो क्या वंशानुक्रम एक शांत सुविधा बनाता है - यह डेटा को विभाजित करने के लिए शांत क्यों है?

  • प्रदर्शन: डेटा का चयन करते समय, हम * से आंकड़े का चयन करते हैं जहां तारीख एक्स और वाई की तारीख होती है, और पोस्टग्रेज केवल टेबल का उपयोग करता है, जहां यह समझ में आता है। उदाहरण के लिए। चयन करें * आंकड़ों से * दिनांक २०१०-० AND-१९ ’और -15 २०१०-०४-१५’ के आंकड़े केवल तालिका के आँकड़े_2010_04 को स्कैन करते हैं, अन्य सभी तालिकाएँ स्पर्श नहीं होंगी - तेज़!
  • सूचकांक आकार: हमारे पास स्तंभ तिथि पर एक बड़े वसा सूचकांक के साथ कोई बड़ी वसा तालिका नहीं है। हमारे पास प्रति माह छोटे टेबल हैं, छोटे सूचकांक के साथ - तेजी से पढ़ता है।
  • रखरखाव: हम प्रत्येक माह की मेज पर वैक्यूम फुल, रेनडेक्स, क्लस्टर चला सकते हैं, अन्य सभी डेटा को लॉक किए बिना

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

मैं टेबल इनहेरिटेंस का भारी उपयोग करता हूं, खासकर जब यह महीने द्वारा समूहीकृत लॉग डेटा को स्टोर करने की बात आती है। संकेत: यदि आप डेटा स्टोर करते हैं, जो कभी नहीं बदलेगा (लॉग डेटा), क्रिएट इंडेक्स ऑन () के साथ (fillfactor = 100) बनाएँ या अनुक्रमित करें; इसका मतलब यह है कि अपडेट के लिए कोई स्थान सूचकांक में आरक्षित नहीं होगा - डिस्क पर सूचकांक छोटा है।

अद्यतन: fillfactor डिफ़ॉल्ट 100 http://www.postgresql.org/docs/9.1/static/sql-createtable.html से है :

तालिका के लिए भराव 10 और 100 के बीच एक प्रतिशत है। 100 (पूर्ण पैकिंग) डिफ़ॉल्ट है



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

4
मूल तालिका पर एक क्वेरी करना प्रभावी रूप से समान है, जो सामान्य पंक्तियों पर प्रत्येक वंश तालिका में एक UNION ALL पर एक क्वेरी निष्पादित करने के समान है। क्वेरी प्लानर चेक विभाजन के बारे में जानते हैं जो प्रत्येक विभाजन को परिभाषित करते हैं, और जब तक कि वे विभाजन को ओवरलैप नहीं करते हैं, यह निर्धारित करने के लिए उनका उपयोग करता है कि यह जाँच तालिकाओं को छोड़ सकता है जिसके लिए CHECKs इंगित करते हैं कि कोई पंक्तियाँ वापस नहीं आएंगी। इस पर डॉक्स पोस्ट करता है
zxq9

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

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

37

"टेबल इनहेरिटेंस" का अर्थ "क्लास इनहेरिटेंस" से कुछ अलग है और वे विभिन्न उद्देश्यों की पूर्ति करते हैं।

Postgres सभी डेटा परिभाषाओं के बारे में है। कभी-कभी वास्तव में जटिल डेटा परिभाषाएं। OOP (सामान्य जावा-रंग की चीजों में) एक परमाणु संरचना में डेटा परिभाषाओं के अधीनस्थ व्यवहार के बारे में है। "वंशानुक्रम" शब्द का उद्देश्य और अर्थ यहाँ काफी भिन्न है।

ओओपी भूमि में मैं परिभाषित कर सकता हूं (यहां वाक्य रचना और शब्दार्थ के साथ बहुत ढीला होना):

import life

class Animal(life.Autonomous):
  metabolism = biofunc(alive=True)

  def die(self):
    self.metabolism = False

class Mammal(Animal):
  hair_color = color(foo=bar)

  def gray(self, mate):
    self.hair_color = age_effect('hair', self.age)

class Human(Mammal):
  alcoholic = vice_boolean(baz=balls)

इसके लिए सारणी इस तरह दिख सकती है:

CREATE TABLE animal
  (name       varchar(20) PRIMARY KEY,
   metabolism boolean NOT NULL);

CREATE TABLE mammal
  (hair_color  varchar(20) REFERENCES hair_color(code) NOT NULL,
   PRIMARY KEY (name))
  INHERITS (animal);

CREATE TABLE human
  (alcoholic  boolean NOT NULL,
   FOREIGN KEY (hair_color) REFERENCES hair_color(code),
   PRIMARY KEY (name))
  INHERITS (mammal);

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

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

CREATE TABLE animal
  (name       varchar(20) PRIMARY KEY,
   ilk        varchar(20) REFERENCES animal_ilk NOT NULL,
   metabolism boolean NOT NULL);

CREATE TABLE mammal
  (animal      varchar(20) REFERENCES animal PRIMARY KEY,
   ilk         varchar(20) REFERENCES mammal_ilk NOT NULL,
   hair_color  varchar(20) REFERENCES hair_color(code) NOT NULL);


CREATE TABLE human
  (mammal     varchar(20) REFERENCES mammal PRIMARY KEY,
   alcoholic  boolean NOT NULL);

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


यदि आप हर ज्ञात स्तनपायी जोड़ रहे हैं तो क्या होगा? क्या आपको स्तनपायी से विरासत में मिला होगा या आपके पास एक विदेशी कुंजी थी जैसे आपने यहां किया था? मेरे पास विदेशी चाबियों के साथ समस्या यह है कि आप इतने सारे जोड़-घटाव करते हैं।
PUK

1
@ पुक आपको सबसे पहले यह तय करना होगा कि आप हर ज्ञात स्तनपायी को क्यों जोड़ रहे हैं। डेटा का आकार उस तरीके से निर्धारित होने वाला है जिससे डेटा का उपयोग किया जाएगा (इस मामले में प्रति जानवर के लिए एक टेबल रखना आवश्यक नहीं है - गेम बेस्टियर के लिए डेटाबेस पर विचार करें जहां आपके पास वास्तव में हर प्रकार की भीड़ है )। ऊपर के मामले में मैं आम तौर पर एक ऐसा दृश्य जोड़ूंगा जो सबसे आम मामला है mammal JOIN human, सिर्फ इसलिए कि हर बार ज्वाइन करना कष्टप्रद है। लेकिन जुड़ने से बचें । जॉइंट्स आरडीबीएमएस में आर डालते हैं। यदि आपको जॉइन पसंद नहीं है तो आपको एक अलग डीबी टाइप का उपयोग करना चाहिए।
zxq9

@ zxq9: मैं अनुमान लगा रहा हूं कि बड़े तालिकाओं के कारण बड़े पैमाने पर अकुशल जोड़ होते हैं, जहां भौतिक विचारों को खेलने में आता है? (मैं उस लंबे समय के लिए पोस्टग्रेज का उपयोग नहीं कर रहा हूं)
मार्क के कोवान

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

1
@ मर्ककॉवन "स्लो" एक सापेक्ष शब्द है। बड़े व्यापार प्रणालियों और गेम सर्वरों में जहां हम क्वेरी वापस करने के लिए ~ 50ms स्वीकार कर सकते हैं, 20 टेबल जॉइन को मेरे अनुभव में कभी भी कोई समस्या नहीं हुई है (पोस्टग्रेज 8+, वैसे भी)। लेकिन ऐसे मामलों में, जब प्रबंधन चाहता है कि <1ms> 10b पंक्ति 5+ तालिकाओं पर बिना सिले डेटा (या व्युत्पन्न मान!) पर जुड़ती है ... दुनिया की कोई भी प्रणाली पिछले महीने इस जॉइन में शामिल होने और इसे चकमा देने के अलावा "तेज" महसूस नहीं करेगी! एक तेज़ K / V स्टोर में (जो अनिवार्य रूप से एक भौतिकवादी दृश्य विशेष परिस्थितियों में कार्य कर सकता है)। लिखने या पढ़ने के समय में ट्रेडऑफ से बच नहीं सकते।
zxq9

6

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

इनहेरिटेंस का उपयोग विभाजन उपकरण के रूप में भी किया जा सकता है । यह विशेष रूप से तब उपयोगी होता है जब आपके पास टेबल हमेशा के लिए बढ़ने वाली हों (लॉग टेबल आदि)।


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

3

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

संपादित करें: एक और अच्छा उपयोग: अपंजीकृत उपयोगकर्ताओं की दो-तालिका से निपटने के साथ , अन्य RDBMSs को दो तालिकाओं को संभालने में समस्या है, लेकिन PostgreSQL में यह आसान है - बस जोड़ दें ONLYजब आप अंतर्निहित "अपंजीकृत उपयोगकर्ता" तालिका में डेटा में हस्तक्षेप नहीं करते हैं।


2

एकमात्र अनुभव जो मुझे विरासत में मिली तालिकाओं के साथ है, विभाजन में है। यह ठीक काम करता है लेकिन यह PostgreSQL के हिस्से का उपयोग करने के लिए सबसे अधिक परिष्कृत और आसान नहीं है।

पिछले हफ्ते हम एक ही OOP मुद्दे को देख रहे थे, लेकिन हमें Hibernate (हमारे सेटअप पसंद नहीं था) के साथ बहुत अधिक समस्याएं थीं, इसलिए हमने PostgreSQL में विरासत का उपयोग नहीं किया।


0

मैं विरासत का उपयोग करता हूं जब मेरे पास तालिकाओं के बीच 1 संबंधों पर 1 से अधिक है।

उदाहरण: मान लीजिए कि आप ऑब्जेक्ट मैप स्थानों को एक्स, वाई, रोटेशन, स्केल के साथ स्टोर करना चाहते हैं।

अब मान लें कि आपके पास मानचित्र पर प्रदर्शित करने के लिए कई अलग-अलग प्रकार के ऑब्जेक्ट हैं और प्रत्येक ऑब्जेक्ट के अपने मानचित्र स्थान पैरामीटर हैं, और मैप पैरामीटर का कभी भी पुन: उपयोग नहीं किया जाता है।

इन मामलों में तालिका विरासत में असमान तालिकाओं को बनाए रखने या स्थान आईडी बनाने और अन्य तालिकाओं को संदर्भित करने से बचने के लिए काफी उपयोगी होगी।


-4

इसका कम से कम उपयोग करें। और इसका मतलब आमतौर पर कभी नहीं होता है, यह संरचनाओं के निर्माण का एक तरीका है जो संबंधपरक मॉडल का उल्लंघन करता है, उदाहरण के लिए सूचना सिद्धांत को तोड़कर और संबंधों के बजाय बैग बनाकर।

इसके बजाय, आगे के सामान्य रूपों सहित उचित संबंधपरक मॉडलिंग के साथ संयुक्त तालिका विभाजन का उपयोग करें।


4
यह सच नहीं है कि PostgreSQLs इनहेरिटेंस फीचर सूचना सिद्धांत को तोड़कर रिलेशनल मॉडल का उल्लंघन करता है। जानकारी सिद्धांत कहते हैं, कि एक संबंधपरक डेटाबेस में सभी डेटा संबंधों में डेटा मान का प्रतिनिधित्व करती है और सभी क्वेरी परिणाम फिर से एक रिश्ता के रूप में प्रतिनिधित्व कर रहे हैं। ( En.wikipedia.org/wiki/Relational_model ) यह हमेशा मामला है, सभी तालिकाओं के बाद से , कि एक और तालिका विरासत में मिली, फिर से साधारण टेबल हैं। उस कारण से "बैग" जैसी कोई चीज नहीं है, जो भी इसका मतलब है।
रोलैंड

2
वैसे, संबंधपरक मॉडल के संबंध में विकिपीडिया शायद ही एक संदर्भ है; यह पहचानने से इनकार करता है कि SQL रिलेशनल मॉडल का उल्लंघन करता है। एक बैग एक चाबी के बिना एक मेज है, क्योंकि संभावित रूप से इसमें डुप्लिकेट हैं, इस प्रकार एक संबंध नहीं है; एक रिश्ता एक सेट होना चाहिए।
लिएंड्रो

यह सुविधा की समस्या नहीं है, लेकिन इसका उपयोग कैसे किया जाता है। यदि आप पहचानकर्ताओं के रूप में uuids के साथ काम करते हैं, तो आपके पास सभी उप-तालिकाओं पर अद्वितीय कुंजियाँ होंगी।
रोलैंड

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