ईएवी - क्या यह वास्तव में सभी परिदृश्यों में खराब है?


65

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

लेकिन मैं सोच रहा हूं कि क्या यह सभी मामलों में गलत है।

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

यह सब मान लिया गया है, कि उत्पाद सूची दिखाने के लिए, यह उत्पाद तालिका में पर्याप्त जानकारी है (जिसका अर्थ है कि कोई ईएवी शामिल नहीं है) और सिर्फ एक उत्पाद दिखाते समय / 5 उत्पादों / आदि की तुलना करते हुए। EAV का उपयोग करके सहेजे गए डेटा का उपयोग किया जाता है।

मैंने Magento के वाणिज्य में इस तरह का दृष्टिकोण देखा है और यह काफी लोकप्रिय है, इसलिए ऐसे मामले हैं जब EAV उचित है?



वास्तव में अच्छी तरह से काम कर रहे ईएवी पैटर्न के उदाहरण के लिए, डाटॉमिक डेटाबेस पर एक नज़र डालें। यह ईएवीटी पैटर्न में सब कुछ संग्रहीत करता है (टी एक "टाइमस्टैम्प" है, वास्तव में लेनदेन आईडी की तरह)। उनका [अनुक्रमण प्रलेखन] (docs.datomic.com/indexes.html) इसे सबसे अच्छा दिखाने के लिए लगता है। ईएवी के एक उदाहरण के लिए बहुत अच्छा काम करना, वर्डप्रेस देखें ।
डैन रोस

जवाबों:


80

https://web.archive.org/web/20140831134758/http://www.dbforums.com/database-concepts-design/1619660-otlt-eav-design-why-do-people-hate.html

ईएवी स्कीमा को आवश्यकतानुसार परिभाषित करने के लिए डेवलपर को एक लचीलापन देता है और यह कुछ परिस्थितियों में अच्छा है।

दूसरी ओर यह एक बीमार परिभाषित क्वेरी के मामले में बहुत खराब प्रदर्शन करता है और अन्य बुरी प्रथाओं का समर्थन कर सकता है।

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


32
अंतिम वाक्य को प्यार करो।
ज़ोहर

2
सड़ा हुआ लिंक। कहीं एक कैश्ड संस्करण है?
वाइल्डकार्ड 1

1
लिंक का अनुसरण न करें। पृष्ठ धीरे-धीरे लोड होता है और सहायक नहीं है। साथ ही, पुराने स्टाइल के फोरम जैसे कि बदबू। इसके बजाय स्टैक ओवरफ्लो का उपयोग करें! अच्छे / उपयोगी उत्तर दें और कूड़ेदान को नीचे धकेलें।
जेस

29

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


16
मैं "बार-बार" की जगह "रन-टाइम में बदलने के लिए ज़रूरतमंद" की आवश्यकता होगी।
डॉक ब्राउन

3
हम काफी अच्छी तरह से समझे गए शब्द "गतिशील" का उपयोग करके आगे भी डॉक्टर ब्राउन को छोटा कर सकते हैं - जब आपकी विशेषताओं की सूची गतिशील रूप से बदल सकती है तो ईएवी उपयोगी है।
अलेक्जेंडर मिल्स

आगे भी "जब आपके गुण बदल सकते हैं" - "गतिशील रूप से" इस संदर्भ में थोड़ा बेमानी है :)
घटिया

1
क्या यह आवश्यक रूप से अधिक उपयोगी है, कहते हैं, एक विशेषता को बदलने के लिए फार्म CREATE TABLEनई विशेषता के लिए प्रदर्शन करते हैं ?
डेमियन यरिक 12

@DamianYerrick दिलचस्प दृष्टिकोण। क्या आपने उत्पादन में इसका उपयोग किया है?
डिगआउट

21

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

के लिए EAV संरचना का उपयोग करने के कई निहितार्थ हैं जो व्यापार बंद हैं।

आप पंक्ति के लिए 'कम स्थान पर व्यापार कर रहे हैं क्योंकि आपके पास 100 कॉलम नहीं हैं जो null' अधिक जटिल प्रश्नों और मॉडल के खिलाफ हैं ।

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

select P.sku
from
  products P
  attrib Ab on (P.sku = Ab.sku and Ab.key = "batteries")
  attrib Ac on (P.sku = Ac.sku and Ac.key = "count")
where
  cast(Ac.value as int) < 4
  and Ab.value = 'C'
  ...

यहाँ महसूस करने वाली बात यह है कि आप मूल्य पर किसी सूचकांक का यथोचित उपयोग नहीं कर सकते हैं। आप किसी को उस चीज़ में डालने से भी नहीं रोक सकते हैं जो वहां पूर्णांक नहीं है, या एक अमान्य पूर्णांक ('-1' बैटरी का उपयोग करता है) क्योंकि मूल्य स्तंभ का उपयोग विभिन्न प्रयोजनों के लिए बार-बार किया जाता है।

इसके बाद उत्पाद के लिए एक मॉडल लिखने की कोशिश में निहितार्थ हैं। आपके पास अच्छे टाइप किए हुए मूल्य होंगे ... लेकिन आप Map<String,String>इसमें हर तरह का सामान रखने के साथ बस बैठे रहने वाले हैं । इसके बाद इसके और भी निहितार्थ हैं जब इसे XML या Json में सीरियल किया जाता है और उन संरचनाओं के खिलाफ सत्यापन या क्वेरी करने की कोशिश की जटिलताएं होती हैं।

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

आपके पास संबंधित टेबल भी हो सकते हैं जिनमें उत्पाद के एक विशिष्ट वर्ग के गुण होते हैं। एक किराने की विभाग की एक और तालिका हो सकती है जिसमें इसके साथ कई विशेषताएँ जुड़ी होती हैं जिनके लिए भवन निर्माण सामग्री की आवश्यकता नहीं होती है (और इसके विपरीत)।

+----------+    +--------+    +---------+
|Grocery   |    |Product |    |BuildMat |
|id (fk)   +--->|id (pk) |<---+id (fk)  |
|expiration|    |desc    |    |material |
|...       |    |img     |    |...      |
+----------+    |price   |    +---------+
                |...     |               
                +--------+               

ऐसे समय होते हैं जो विशेष रूप से ईएवी तालिका के लिए कहते हैं।

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

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

इसके बजाय, आप व्यवस्थापकीय इंटरफ़ेस को EAV तालिका में बनाते हैं और इसका उपयोग करने की अनुमति देते हैं। यदि ग्राहक 'पोलकडॉट्स' के लिए एक प्रविष्टि बनाना चाहता है, तो यह ईएवी तालिका में जाता है और आप पहले से ही जानते हैं कि इससे कैसे निपटना है।

इसका एक उदाहरण Redmine के लिए डेटाबेस मॉडल में देखा जा सकता है आप custom_fields टेबल देख सकते हैं, और custom_values ​​टेबल - वे EAV के कुछ भाग हैं जो सिस्टम को विस्तारित करने की अनुमति देते हैं।


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

आप इन्वेंट्री प्रबंधन प्रणाली के लिए SQL बनाम NoSQL पढ़ना चाह सकते हैं

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

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

एक बार जब आप इस रास्ते पर चले जाते हैं, तो आपको कुछ ऐसा मिल सकता है जो वास्तव में आप जिस चीज की तलाश कर रहे हैं ... वह सब कुछ ट्रेडऑफ के साथ आता है।


10

6 साल बाद

अब जब JSON in Postgres यहाँ है, हमारे पास एक और विकल्प है, जो लोग Postgres का उपयोग कर रहे हैं। यदि आप केवल किसी उत्पाद में कुछ अतिरिक्त डेटा संलग्न करना चाहते हैं, तो आपकी आवश्यकताएं काफी सरल हैं। उदाहरण:

CREATE TABLE products (sku VARCHAR(30), shipping_weight REAL, detail JSON);
INSERT INTO products ('beachball', 1.0, '{"colors": ["red", "white"], "diameter": "50cm"}');

SELECT * FROM products;
    sku    | weight |               detail               
-----------+--------+------------------------------------
 beachball |      1 | {"colors": ["red", "white"], "diameter": "50cm"}

यहाँ JSON in Postgres में एक स्मूद परिचय दिया गया है: https://www.compose.com/articles/is-postgresql-your-next-json-database/

ध्यान दें कि पोस्टग्रैज वास्तव में JSONB को स्टोर करता है, न कि प्लेन टेक्स्ट JSON को, और यह JSONB डॉक्यूमेंट / फील्ड के अंदर फ़ील्ड्स पर इंडेक्स का समर्थन करता है, अगर आपको पता चलता है कि आप वास्तव में उस डेटा के खिलाफ क्वेरी करना चाहते हैं।

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

यह उत्तर सीधे प्रश्न को संबोधित नहीं कर सकता है, लेकिन यह एक ईएवी पैटर्न के लिए एक विकल्प प्रदान करता है, जिसे मूल प्रश्न पर विचार करने वाले किसी व्यक्ति द्वारा विचार किया जाना चाहिए।


3
मुझे लगता है कि वैकल्पिक समाधान पोस्ट करना बहुत अच्छा विचार है। बस दूसरों को ट्रैक पर रखने के लिए, एमएस SQL ​​कुछ समय के लिए उन्हें अनुक्रमित करने की क्षमता के साथ XML स्तंभों का समर्थन कर रहा था और 2016 से शुरू होकर यह JSON के साथ भी कर सकता है (हालांकि JSON MS SQL में एक मूल स्तंभ प्रकार नहीं है, फिर भी आप इसे अनुक्रमित कर सकते हैं )। दूसरी ओर - मैंने जो पढ़ा है, उससे JSON का समर्थन बेहतर है, उदाहरण के लिए ऐसा लगता है कि यह JSON सरणी गुणों में डेटा पर समर्थन अनुक्रमित करता है।
गिदरीस

1
"... JSONB फ़ील्ड के भीतर फ़ील्ड्स को अलग-अलग क्वेरी के साथ व्यक्तिगत रूप से संशोधित नहीं किया जा सकता है; आपको JSONB फ़ील्ड की संपूर्ण सामग्री को बदलना होगा।" यह पुराना है, है ना? jsonb_set()Postgres 9.5 में एक फ़ंक्शन है और बाद में जो वास्तव में इसके लिए है। (लेख आप 9.5 फीचर परिवर्धन पर चर्चा करने के लिए एक नए लेख के लिए लिंक से जुड़े हुए हैं ।)
वाइल्डकार्ड

7

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

एक लंबी पतली तालिका में डेटा को अलग करने के सामान्य मामले के लिए ... यदि आप की जरूरत है, तो आपको नई टेबल बनाने से डरना नहीं चाहिए , और सिर्फ एक या दो लंबे पतला टेबल होने से केवल एक या अधिक होने से बेहतर नहीं है दो छोटी मोटी मेजें।

कहा जा रहा है, मैं लॉगिंग के लिए ईएवी तालिकाओं का उपयोग करने के लिए कुख्यात हूं। उनकी कुछ अच्छी उपयोगिता है।


कृपया "स्कीनी टेबल" और "फैट टेबल" को परिभाषित करें।
ट्यूलेंस कोर्डोवा

@ TulainsCórdova: एक "स्किनी" टेबल कुछ पंक्तियों और कई कॉलमों के साथ एक होगी, जबकि एक मोटी टेबल कई कॉलम और कुछ पंक्तियों के साथ एक है। एक उदाहरण एक लुकअप टेबल का निर्माण होगा जहां आपके पास कहने के लिए गुण हैं, किताबें। एक मोटी तालिका में प्रति पुस्तक एक रिकॉर्ड होगा, जिसमें डेटा के विशिष्ट टुकड़ों के लिए कई कॉलम होंगे, जबकि एक पतली तालिका में शायद चार कॉलम आईडी, पुस्तक, field_name, field_data होगा। पहले का लाभ यह है कि कम रिकॉर्ड हैं, लेकिन नकारात्मक यह है कि कुछ क्षेत्र खाली हो सकते हैं, और पूरी बात का विस्तार करना कठिन है।
सैटेनिकपॉपी 16

@Satanicpuppy मुझे लगता है कि आपकी पतली / मोटी परिभाषाएं मिश्रित हैं - वे समान हैं। क्या आपका मतलब है कि एक पतली तालिका में कुछ कॉलम और कई पंक्तियाँ हैं?
चार्ल्स वुड

1

ईएवी स्पष्ट संरचना की समस्या को निहित धारणा में बदल देता है। यह कहने के बजाय कि X, A और B के स्तंभों वाली तालिका है। आप A और B फॉर्म तालिका X को स्तंभित करते हैं। यह एक अर्थ में रिवर्स है, लेकिन आवश्यक रूप से एक-से-एक मैपिंग नहीं है। आप कह सकते हैं कि ए और बी दोनों तालिका (या प्रकार) के लिए एक्स और वाई दोनों मानचित्र। यह अधिक शामिल डोमेन में महत्वपूर्ण हो सकता है जहां संदर्भ मायने रखता है।

मैं इस प्रकार के दृष्टिकोण के लिए डाटोमिक का अध्ययन कर रहा हूं और मुझे लगता है कि यह एक बहुत ही उपयोगी और शक्तिशाली प्रणाली है जिसकी सीमाएं आपको इसके साथ करनी चाहिए (ऐसा नहीं कि आप नहीं कर सकते)।

यह ईएवी धीमा होगा, या "आपको अपने आप को फांसी देने के लिए पर्याप्त रस्सी देगा" एक ऐसा बयान नहीं है जिससे मैं सहमत होऊंगा। इसके बजाय, मैं ईएवी की ताकत पर अधिक जोर दूंगा और यदि यह आपकी समस्या का कारण बनता है, तो आपको इस पर विचार करना चाहिए।

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

ईएवी के साथ समस्या मेरे दिमाग में डेटोमिक जैसे कार्यान्वयन की कमी के साथ है। चूंकि यह ईएवी के बारे में एक सवाल है, मैं डेटोमिक के बारे में नहीं जानना चाहता हूं, लेकिन यह उन चीजों में से एक है, जहां मुझे लगता है कि उन्हें ईएवी के संबंध में सब कुछ सही मिला है।

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