डिज़ाइन बहस: वर्जन वाली ऑब्जेक्ट्स को स्टोर और हेरफेर करने के अच्छे तरीके क्या हैं?

मैं जानबूझकर इस अस्पष्ट को पहले छोड़ रहा हूं। मैं चर्चा की तलाश में हूं और कठोर उत्तरों की तलाश में मुझे कौन से मुद्दे महत्वपूर्ण हैं।

मैं एक ऐप डिजाइन करने के बीच में हूं जो पोर्टफोलियो प्रबंधन की तरह कुछ करता है। मेरे पास अब तक का डिज़ाइन है

  • Problem: a problem that needs to be solved
  • Solution: a proposed solution to one or more problems
  • Relationship: a relationship among two problems, two solutions, or a problem and a solution. Further broken down into:
    • Parent-child - some sort of categorization/tree hierarchy
    • Overlap - the degree to which two solutions or two problems really address the same concept
    • Addresses - the degree to which a problem addresses a solution

मेरा सवाल इन चीजों की अस्थायी प्रकृति के बारे में है। समस्याएं फसल, फिर फीका। समाधानों की अपेक्षाकृत संकल्प दिनांक है, लेकिन इसे विकसित किए जाने के रूप में संशोधित किया जा सकता है। एक रिश्ते की डिग्री समय के साथ बदल सकती है क्योंकि समस्याएं और समाधान विकसित होते हैं।

तो, सवाल: इन चीजों के संस्करण के लिए सबसे अच्छा डिजाइन क्या है, इसलिए मैं अपने पोर्टफोलियो का वर्तमान और ऐतिहासिक परिप्रेक्ष्य दोनों प्राप्त कर सकता हूं?

बाद में: शायद मुझे इसे एक और विशिष्ट सवाल बनाना चाहिए, हालांकि @ एरिक दाढ़ी का जवाब एक लायक है।

मैंने तीन डेटाबेस डिज़ाइनों पर विचार किया है। मैं अपनी कमियों को दिखाने के लिए प्रत्येक के लिए पर्याप्त होगा। मेरा सवाल है: कौन सा चुनना है, या आप कुछ बेहतर सोच सकते हैं?

1: समस्याएं (और अलग से, समाधान) संस्करण में आत्म-संदर्भित हैं।

table problems
  int id | string name | text description | datetime created_at | int previous_version_id

  foreign key previous_version_id -> problems.id

यह समस्याग्रस्त है क्योंकि हर बार जब मैं एक नया संस्करण चाहता हूं, तो मुझे उस पूरे विवरण कॉलम सहित पूरी पंक्ति को डुप्लिकेट करना होगा।

2: एक नया रिश्ता प्रकार बनाएँ: संस्करण।

table problems
  int id | string name | text description | datetime created_at

यह रिश्ते तालिका में समस्याएं और समाधान तालिकाओं से रिश्ते को स्थानांतरित करता है। वही डुप्लिकेशन समस्या, लेकिन शायद थोड़ा "क्लीनर" क्योंकि मेरे पास पहले से ही एक अमूर्त रिलेशनशिप अवधारणा है।

3: एक और सबवर्सन-जैसी संरचना का उपयोग करें; सभी समस्या और समाधान विशेषताओं को एक अलग तालिका में ले जाएं और उन्हें संस्करण दें।

table problems
  int id

table attributes
  int id | int thing_id | string thing_type | string name | string value | datetime created_at | int previous_version_id

  foreign key (thing_id, thing_type) -> problems.id or solutions.id
  foreign key previous_version_id -> attributes.id

इसका मतलब है कि किसी समस्या या समाधान के वर्तमान संस्करण को लोड करने के लिए मुझे विशेषता के सभी संस्करणों को लाने के लिए, उन्हें तिथि के अनुसार क्रमबद्ध करें और फिर सबसे वर्तमान का उपयोग करें। यह भयानक नहीं हो सकता है। मेरे लिए वास्तव में बुरा लगता है कि मैं डेटाबेस में इन विशेषताओं को टाइप-चेक नहीं कर सकता। वह मान कॉलम फ्री-टेक्स्ट होना चाहिए। मैं name कॉलम को एक अलग attribute_names तालिका में एक संदर्भ बना सकता हूं जिसमें type कॉलम है, लेकिन यह बल नहीं विशेषताएँ तालिका में सही प्रकार।

बाद में अभी भी: बहु-टेबल विदेशी कुंजी के बारे में @Eric Beard की टिप्पणियों के जवाब:

हां, मैंने जो वर्णन किया है वह सरल है: केवल दो प्रकार की चीजें हैं (समस्याएं और समाधान)। मेरे पास वास्तव में लगभग 9 या 10 विभिन्न प्रकार की चीजें हैं, इसलिए आपकी रणनीति के तहत मेरे पास 9 या 10 कॉलम विदेशी कुंजी होंगे। मैं सिंगल-टेबल विरासत का उपयोग करना चाहता था, लेकिन चीजों में इतनी कम आम बात है कि यह बेहद एक टेबल में गठबंधन करने के लिए अपर्याप्त होगा।

0
ro fr bn

4 उत्तर

हम्म, इस साइट की तरह लगता है ...

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

0
जोड़ा

@Gaius

foreign key (thing_id, thing_type) -> problems.id or solutions.id

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

problem_id and solution_id 

बहुत बेहतर काम करेगा।

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

0
जोड़ा
उन विदेशी चाबियों के रूप में वोट दिया जो विभिन्न तालिकाओं पर जाते हैं ताकि अनुकूलक को भ्रमित कर सकें। जब आप अभिभावक रिकॉर्ड और आरआई के लिए हटाते हैं तो यह भी बुरा होता है।
जोड़ा लेखक WW., स्रोत

मुझे लगता है कि वहाँ है

विकल्प 4: संकर

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

यदि वर्णन और अन्य बड़े फ़ील्ड चीजें तालिका में रहते हैं, हालांकि, यह डुप्लिकेशन-स्थान समस्या को हल नहीं करता है।

table things
  int id | int type | string name | text description | datetime created_at | other common fields...
  foreign key type -> thing_types.id

table custom_attributes
  int id | int thing_id | string name | string value
  foreign key thing_id -> things.id
0
जोड़ा

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

मेरे पास समस्या, समाधान और रिश्ते के लिए टेबल होंगे जो वर्तमान स्थिति का प्रतिनिधित्व करते हैं। एक problem_history , solution_history , आदि तालिका भी होगी। ये समस्या की बाल सारणी होगी लेकिन इसमें VersionNumber और प्रभावी दिनांक के लिए अतिरिक्त कॉलम भी शामिल होंगे। कुंजी होगी ( ProblemId , VersionNumber )।

जब आप किसी समस्या को अद्यतन करते हैं, तो आप पुराने मान problem_history तालिका में लिखेंगे। समय-समय पर प्रश्नों को इंगित करना संभव है क्योंकि आप problem_history रिकॉर्ड चुन सकते हैं जो किसी विशेष तिथि के अनुसार मान्य है।

जहां मैंने पहले यह किया है, मैंने यूनियन <�कोड> समस्या और problem_history पर भी एक दृश्य बनाया है क्योंकि यह कभी-कभी विभिन्न प्रश्नों में उपयोगी होता है।

विकल्प 1 वर्तमान स्थिति से पूछताछ करना मुश्किल बनाता है, क्योंकि आपके सभी ऐतिहासिक डेटा को आपके वर्तमान डेटा के साथ मिश्रित किया जाता है।

विकल्प 3 क्वेरी प्रदर्शन के लिए खराब होगा और कोड के लिए बुरा होगा क्योंकि आप बहुत सी पंक्तियों तक पहुंच पाएंगे, केवल एक साधारण क्वेरी क्या होनी चाहिए।

0
जोड़ा