कई प्रकार के उत्पाद के लिए उत्पाद तालिका कैसे डिज़ाइन करें जहां प्रत्येक उत्पाद के कई पैरामीटर हैं


140

मुझे टेबल डिजाइन का ज्यादा अनुभव नहीं है। मेरा लक्ष्य एक या अधिक उत्पाद तालिकाएँ बनाना है जो नीचे की आवश्यकताओं को पूरा करती हैं:

  • कई प्रकार के उत्पादों (टीवी, फोन, पीसी, ...) का समर्थन करें। प्रत्येक प्रकार के उत्पाद में मापदंडों का एक अलग सेट होता है, जैसे:

    • फोन में कलर, साइज, वजन, OS होगा ...

    • PC में CPU, HDD, RAM होगा ...

  • मापदंडों का सेट गतिशील होना चाहिए। आप अपने पसंद के किसी भी पैरामीटर को जोड़ या संपादित कर सकते हैं।

मैं हर तरह के उत्पाद के लिए एक अलग तालिका के बिना इन आवश्यकताओं को कैसे पूरा कर सकता हूं?

जवाबों:


233

आपके पास वर्णन करने वाले पदानुक्रम के मॉडलिंग के लिए कम से कम ये पाँच विकल्प हैं:

  • सिंगल टेबल इनहेरिटेंस : सभी प्रकार की सभी विशेषताओं को संग्रहीत करने के लिए पर्याप्त कॉलम के साथ सभी प्रकार के उत्पाद के लिए एक टेबल। इसका अर्थ बहुत सारे कॉलम हैं, जिनमें से अधिकांश किसी भी पंक्ति में NULL हैं।

  • क्लास टेबल इनहेरिटेंस : उत्पाद के लिए एक तालिका, सभी उत्पाद प्रकारों के लिए सामान्य विशेषताओं को संग्रहीत करती है। फिर प्रति उत्पाद प्रकार की एक तालिका, उस उत्पाद प्रकार के लिए विशिष्ट विशेषताओं को संग्रहीत करती है।

  • कंक्रीट टेबल इनहेरिटेंस : आम उत्पाद विशेषताओं के लिए कोई तालिका नहीं। इसके बजाय, प्रति उत्पाद प्रकार एक तालिका, दोनों सामान्य उत्पाद विशेषताओं और उत्पाद-विशिष्ट विशेषताओं को संग्रहीत करते हैं।

  • सीरियलाइज्ड LOB : प्रोडक्ट्स के लिए एक टेबल, सभी उत्पाद प्रकारों के लिए सामान्य विशेषताओं को संग्रहीत करता है। एक अतिरिक्त स्तंभ XML, YAML, JSON, या कुछ अन्य प्रारूप में एक संरचित डेटा का BLOB संग्रहीत करता है। यह BLOB आपको प्रत्येक उत्पाद प्रकार के लिए विशिष्ट विशेषताओं को संग्रहीत करने की अनुमति देता है। आप इसका वर्णन करने के लिए फैंसी डिज़ाइन पैटर्न का उपयोग कर सकते हैं, जैसे कि फसाडे और मेमेंटो। लेकिन परवाह किए बिना आपके पास ऐसी विशेषताओं का एक समूह है, जिन्हें आसानी से SQL के भीतर नहीं दिखाया जा सकता है; आपको पूरी तरह से ब्लॉब को एप्लिकेशन पर वापस लाना होगा और उसे वहां से सुलझाना होगा।

  • इकाई-गुण-मूल्य : उत्पादों के लिए एक तालिका, और एक तालिका जिसमें पिवोट्स स्तंभों के बजाय पंक्तियों को दर्शाते हैं। EAV संबंधपरक प्रतिमान के संबंध में एक वैध डिजाइन नहीं है, लेकिन कई लोग इसे वैसे भी उपयोग करते हैं। यह एक अन्य उत्तर द्वारा उल्लिखित "गुण पैटर्न" है। कुछ नुकसान के लिए StackOverflow पर ईआरवी टैग के साथ अन्य प्रश्न देखें ।

मैंने एक प्रस्तुति में इसके बारे में अधिक लिखा है, एक्सटेंसिबल डेटा मॉडलिंग


ईएवी के बारे में अतिरिक्त विचार: हालांकि कई लोग ईएवी के पक्ष में लगते हैं, मैं नहीं। यह सबसे लचीला समाधान की तरह लगता है, और इसलिए सबसे अच्छा है। हालांकि, ध्यान TANSTAAFL ध्यान रखें । यहाँ EAV के कुछ नुकसान हैं:

  • किसी कॉलम को अनिवार्य (समकक्ष NOT NULL) बनाने का कोई तरीका नहीं ।
  • प्रविष्टियों को मान्य करने के लिए SQL डेटा प्रकारों का उपयोग करने का कोई तरीका नहीं है।
  • यह सुनिश्चित करने का कोई तरीका नहीं है कि विशेषता नाम लगातार वर्तनी हैं।
  • लुकअप टेबल के लिए किसी दिए गए विशेषता के मूल्यों पर एक विदेशी कुंजी लगाने का कोई तरीका नहीं है।
  • एक पारंपरिक सारणीबद्ध लेआउट में परिणाम प्राप्त करना जटिल और महंगा है, क्योंकि JOINप्रत्येक विशेषता के लिए आपको कई पंक्तियों से विशेषताएँ प्राप्त करने की आवश्यकता होती है ।

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

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

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


अपडेट 2019: जितना अधिक मैं JSON का उपयोग "कई कस्टम विशेषताओं" समस्या के समाधान के रूप में कर रहा हूं, उतना ही कम मुझे वह समाधान पसंद है। यह विशेष JSON फ़ंक्शंस का उपयोग करते हुए भी प्रश्नों को बहुत जटिल बनाता है। JSON दस्तावेज़ों को संग्रहीत करने के लिए, सामान्य पंक्तियों और स्तंभों में संग्रहीत करने के लिए यह बहुत अधिक संग्रहण स्थान लेता है।

मूल रूप से, इनमें से कोई भी समाधान संबंधपरक डेटाबेस में आसान या कुशल नहीं है। "चर विशेषताएँ" होने का पूरा विचार मौलिक रूप से संबंधपरक सिद्धांत के साथ बाधाओं पर है।

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


11
@HimalayaGarg विकल्प "4.5" वास्तव में बिल के पोस्ट के पूरे बिंदु के विपरीत है।
user3308043

2
MySQL के विपरीत, SQL सर्वर में XML, XPath और XQuery के लिए व्यापक समर्थन है। तो SQL सर्वर के उपयोगकर्ताओं के लिए, सबसे अच्छा विकल्प एक्सएमएल प्रकार (विकल्प 4) के एक कॉलम में अतिरिक्त विशेषताओं को संग्रहीत करना होगा। इस तरह से आपको "पूरे ब्लॉब को एप्लिकेशन पर वापस लाना होगा और वहां छाँटना होगा।" तुम भी SQL सर्वर में XML स्तंभों पर अनुक्रमित बना सकते हैं।
डेल्फी.बॉय


2
मैं अपने मामले के लिए सीरियल LOB पसंद करता हूं। लेकिन क्या यह ओआरएम के लिए उपयुक्त है? मैं ईएफ का उपयोग करता हूं।
महमूद जेनमी

@ user2741577, निश्चित रूप से, लेकिन आपको संभवतः असंबंधित डेटा के क्षेत्रों को LOB बनाने के लिए कस्टम कोड लिखना होगा और उन्हें अपने ORM ऑब्जेक्ट के प्रत्येक निकाय क्षेत्र में लागू करना होगा। मैं EF नहीं जानता, लेकिन मुझे लगता है कि आप ऐसा करने वाला एक आधार ORM वर्ग बना सकते हैं। आपको डेटाबेस पंक्ति के कंक्रीट फ़ील्ड से कौन से फ़ील्ड आए, और कौन से फ़ील्ड LOB के फ़ील्ड से आए, इस पर नज़र रखने की आवश्यकता है, इसलिए आप ऑब्जेक्ट को सहेजने का समय होने पर एक LOB बना सकते हैं।
बिल कार्विन

12

@पतथर दिल

मैं पूरे रास्ते ईएवी और एमवीसी के साथ यहां जाऊंगा।

@ बिल कार्विन

यहाँ EAV के कुछ नुकसान हैं:

  • कॉलम को अनिवार्य करने का कोई तरीका नहीं (NULL के बराबर) नहीं।
  • प्रविष्टियों को मान्य करने के लिए SQL डेटा प्रकारों का उपयोग करने का कोई तरीका नहीं है।
  • यह सुनिश्चित करने का कोई तरीका नहीं है कि विशेषता नाम लगातार वर्तनी हैं।
  • लुकअप टेबल के लिए किसी दिए गए विशेषता के मूल्यों पर एक विदेशी कुंजी लगाने का कोई तरीका नहीं है।

उन सभी चीजों को जिनका आपने यहां उल्लेख किया है:

  • डेटा मान्य
  • विशेषता नाम वर्तनी सत्यापन है
  • अनिवार्य कॉलम / फ़ील्ड
  • निर्भर विशेषताओं के विनाश से निपटने

मेरी राय में एक डेटाबेस में बिल्कुल भी नहीं है क्योंकि कोई भी डेटाबेस उन इंटरैक्शन और आवश्यकताओं को एक उचित स्तर पर संभालने में सक्षम नहीं है जैसा कि एक एप्लिकेशन की प्रोग्रामिंग भाषा करती है।

इस तरह से डेटाबेस का उपयोग करना मेरी राय में एक नाखून को हथौड़ा करने के लिए एक चट्टान का उपयोग करने जैसा है। आप इसे एक चट्टान के साथ कर सकते हैं लेकिन क्या आप एक हथौड़ा का उपयोग करने के लिए नहीं हैं जो अधिक सटीक है और विशेष रूप से इस तरह की गतिविधि के लिए डिज़ाइन किया गया है?

एक पारंपरिक सारणीबद्ध लेआउट में परिणाम प्राप्त करना जटिल और महंगा है, क्योंकि कई पंक्तियों से विशेषता प्राप्त करने के लिए आपको प्रत्येक विशेषता के लिए JOIN करना होगा।

यह समस्या आंशिक डेटा पर कुछ प्रश्न बनाकर और उन्हें आपके आवेदन के साथ सारणीबद्ध लेआउट में संसाधित करके हल की जा सकती है। यहां तक ​​कि अगर आपके पास 600GB उत्पाद डेटा है, तो आप इसे बैचों में संसाधित कर सकते हैं, यदि आपको इस तालिका में प्रत्येक पंक्ति से डेटा की आवश्यकता हो।

आगे जाकर यदि आप प्रश्नों के प्रदर्शन में सुधार करना चाहते हैं, तो आप कुछ कार्यों जैसे कि रिपोर्टिंग या वैश्विक पाठ खोज के लिए चयन कर सकते हैं और उनके लिए तैयार कर सकते हैं सूचकांक तालिकाएँ जो आवश्यक डेटा संग्रहीत करती हैं और समय-समय पर पुनर्जीवित होती हैं, प्रत्येक 30 मिनट में कहने की अनुमति देता है।

आपको अतिरिक्त डेटा संग्रहण की लागत से चिंतित होने की आवश्यकता नहीं है क्योंकि यह हर दिन सस्ता और सस्ता हो जाता है।

यदि आप अभी भी एप्लिकेशन द्वारा किए गए संचालन के प्रदर्शन से चिंतित हैं, तो आप डेटा को पूर्व-संसाधित करने के लिए Erlang, C ++, Go Language का उपयोग कर सकते हैं और बाद में सिर्फ अपने मुख्य ऐप में अनुकूलित डेटा को आगे संसाधित कर सकते हैं।


you can always use Erlang, C++, Go Language to pre-process the dataआप क्या मतलब था? DB के बजाय, गो लैंग का उपयोग करें? क्या आप कृपया उस पर विस्तार कर सकते हैं?
ग्रीन

1
मैं पूरी तरह सहमत हूँ। ईएवी जाने का एक तरीका है, खासकर अगर आपको फ्लेक्सिबलिटी के स्तर की आवश्यकता है जो आपको डीबी स्कीमा परिवर्तनों के बिना नए प्रकार के उत्पादों और मापदंडों को जोड़ने की अनुमति देगा, मेरा मतलब है कि आपके एप्लिकेशन के माध्यम से उत्पादन में रहते हैं। वहाँ किया गया था कि। मेरे लिए काम किया। धीमी पूछताछ के बारे में ... क्या यहाँ किसी ने कभी कैश के बारे में सुना है? ;)
pawel.kalisz

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

6

अगर मैं Class Table Inheritanceअर्थ का उपयोग करता हूं :

उत्पाद के लिए एक तालिका, सभी उत्पाद प्रकारों के लिए सामान्य गुण संग्रहीत करती है। फिर प्रति उत्पाद प्रकार की एक तालिका, उस उत्पाद प्रकार के लिए विशिष्ट विशेषताओं को संग्रहीत करती है। -बिल कार्विन

जो मुझे बिल कारविन के सुझावों में से सबसे ज्यादा पसंद है .. मैं एक तरह की कमी को दूर कर सकता हूं, जिसे मैं यह बताने की कोशिश करूंगा कि समस्या बनने से कैसे बचा जाए।

मुझे कौन सी आकस्मिक योजना चाहिए, जब एक विशेषता जो केवल 1 प्रकार के लिए सामान्य है, फिर 2 से सामान्य हो जाती है, तो 3, आदि?

उदाहरण के लिए: (यह सिर्फ एक उदाहरण है, मेरा असली मुद्दा नहीं)

यदि हम फर्नीचर बेचते हैं, तो हम कुर्सियां, लैंप, सोफा, टीवी आदि बेच सकते हैं। टीवी प्रकार एकमात्र प्रकार हो सकता है जिसे हम बिजली की खपत करते हैं। तो मैं इस power_consumptionविशेषता पर डालूँगा tv_type_table। लेकिन फिर हम होम थिएटर सिस्टम को शुरू करना चाहते हैं जिसमें एक power_consumptionसंपत्ति भी है । ठीक है इसके सिर्फ एक अन्य उत्पाद तो मैं इस क्षेत्र को भी जोड़ दूंगा stereo_type_tableक्योंकि यह इस बिंदु पर सबसे आसान है। लेकिन समय के साथ-साथ जब हम अधिक से अधिक इलेक्ट्रॉनिक्स ले जाना शुरू करते हैं, तो हमें एहसास होता power_consumptionहै कि यह व्यापक है कि इसमें होना चाहिए main_product_table। अब मुझे क्या करना चाहिए?

फ़ील्ड को इसमें जोड़ें main_product_table। इलेक्ट्रॉनिक्स लूप करने के लिए एक स्क्रिप्ट लिख सकते हैं और प्रत्येक से सही मान डाल type_tableकरने के लिए main_product_table। फिर उस कॉलम को प्रत्येक से ड्रॉप करें type_table

अब यदि मैं हमेशा GetProductDataउत्पाद जानकारी खींचने के लिए डेटाबेस के साथ बातचीत करने के लिए एक ही वर्ग का उपयोग कर रहा था ; फिर अगर कोड में किसी भी बदलाव के लिए अब रिफैक्टिंग की जरूरत है, तो वे केवल उस वर्ग के लिए होना चाहिए।


3

आपके पास एक उत्पाद तालिका और 3 कॉलम के साथ एक अलग ProductAdditionInfo तालिका हो सकती है: उत्पाद ID, अतिरिक्त जानकारी नाम, अतिरिक्त जानकारी मान। यदि रंग का उपयोग कई नहीं बल्कि सभी प्रकार के उत्पादों द्वारा किया जाता है, तो आप उत्पाद तालिका में एक अशक्त स्तंभ हो सकते हैं, या इसे ProductAdditionalInfo में डाल सकते हैं।

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

स्टीव येजे ने इसे प्रॉपर्टीज़ पैटर्न कहा है और इसे इस्तेमाल करने के बारे में एक लंबी पोस्ट लिखी है।


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

2
सच कहूं तो, जब मैंने @Bills के उत्तर में EAV का वर्णन पढ़ा तो मुझे समझ में नहीं आया कि वह क्या समझा रहा था। लेकिन जब आपने कहा कि 3 columns: product ID, additional info name, additional info valueमैं अवधारणा को समझ गया हूं। और मैंने वास्तव में पहले भी ऐसा किया है, और समस्याओं में भाग गया। हालाँकि, मुझे इस समय यह याद नहीं है कि वे समस्याएं क्या थीं।
JD यशैक

1
@JDIsaacks इस पैटर्न में, एक आम समस्या यह है कि हम यह नहीं जानते हैं कि सभी विशेषताओं को लाने के लिए हमें कितने JOIN की आवश्यकता है।
ओमिड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.