2013-06-15 6 views
5

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

प्रत्येक उत्पाद में कई अलग-अलग गुण हो सकते हैं।

मैं डेटाबेस मॉडल जो मूल रूप से है उपयोग कर रहा हूँ (लिंक देखें) http://www.damirsystems.com/dp_images/product_model_01.png

मैं एक बड़ा डेटाबेस है, जो उत्पाद तालिका में 500000 के बारे में उत्पाद युक्त है।

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

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

उत्तर

22

जो मॉडल आप लिंक करते हैं वह आंशिक entity–attribute–value (ईएवी) मॉडल जैसा दिखता है। ईएवी बहुत लचीला है, लेकिन खराब डेटा अखंडता प्रदान करता है, और यह बोझिल और आमतौर पर अक्षम है। यह वास्तव में संबंधपरक मॉडल की भावना में नहीं है। कुछ बड़ी ई-कॉमर्स साइटों पर काम करने के बाद, मैं आपको बता सकता हूं कि यह इस क्षेत्र में मानक या अच्छी डेटाबेस डिजाइन अभ्यास नहीं है।

यदि आपके पास उत्पाद की एक बड़ी संख्या नहीं है (दसियों तक, लेकिन सैकड़ों नहीं) तो आप इसे दो सामान्य दृष्टिकोणों में से एक का उपयोग करके संभाल सकते हैं।

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

create table Product (
    id integer primary key, 
    name varchar(255) not null, 
    type char(1) not null check (type in ('B', 'M', 'V')), 
    number_of_pages integer, -- book only 
    duration_in_seconds integer, -- music and video only 
    classification varchar(2) check (classification in ('U', 'PG', '12', '15', '18')) -- video only 
); 

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

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

check ((case when type = 'B' then (number_of_pages is not null) else true end))) 

(टोपी वहाँ जो सेलको को टिप - मैं ऊपर देखा कैसे एसक्यूएल में तार्किक निहितार्थ करने के लिए, और एक उदाहरण है जहां वह इसे इस निर्माण के साथ करता है एक बहुत ही इसी तरह की जांच बाधा के निर्माण के लिए पाया जाता है)

आप भी कह सकते हैं:

check ((case when type = 'B' then (number_of_pages is not null) else (number_of_pages is null) end))) 

यह सुनिश्चित करने के लिए कि किसी भी पंक्ति में उसके कॉल के लिए उपयुक्त कॉलम में कोई मान न हो।

दूसरा दृष्टिकोण एकाधिक तालिकाओं का उपयोग करना है: एक बेस टेबल सभी उत्पादों के लिए कॉलम कॉलम, और उस प्रकार के उत्पादों के लिए विशिष्ट प्रत्येक प्रकार के उत्पाद होल्डिंग कॉलम के लिए एक सहायक तालिका।तो:

create table Product (
    id integer primary key, 
    type char(1) not null check (type in ('B', 'M', 'V')), 
    name varchar(255) not null 
); 

create table Book (
    id integer primary key references Product, 
    number_of_pages integer not null 
); 

create table Music (
    id integer primary key references Product, 
    duration_in_seconds integer not null 
); 

create table Video (
    id integer primary key references Product, 
    duration_in_seconds integer not null, 
    classification varchar(2) not null check (classification in ('U', 'PG', '12', '15', '18')) 
); 

ध्यान दें कि सहायक तालिकाओं में मुख्य तालिका के समान प्राथमिक कुंजी है; उनकी प्राथमिक कुंजी कॉलम मुख्य तालिका के लिए एक विदेशी कुंजी भी है।

यह दृष्टिकोण अभी भी काफी सरल है, और ईमानदारी को लागू करने का बेहतर काम करता है। प्रश्नों आम तौर पर शामिल मिलती है, हालांकि:

select 
    p.id, 
    p.name 
from 
    Product p 
    join Book b on p.id = b.id 
where 
    b.number_of_pages > 300; 

वफ़ादारी अभी भी सही नहीं है, क्योंकि यह मुख्य तालिका में गलत प्रकार की एक पंक्ति के लिए इसी एक सहायक टेबल में एक पंक्ति बनाने के लिए संभव है, या में पंक्तियों बनाने के लिए मुख्य तालिका में एक पंक्ति के अनुरूप एकाधिक सहायक टेबल। आप मॉडल को फिर से परिशोधित करके इसे ठीक कर सकते हैं। यदि आप प्राथमिक कुंजी को एक समग्र कुंजी बनाते हैं जिसमें टाइप कॉलम शामिल होता है, तो किसी उत्पाद का प्रकार इसकी प्राथमिक कुंजी में एम्बेड किया जाता है (एक पुस्तक में प्राथमिक कुंजी होगी ('बी', 1001))। आपको सहायक टेबल में टाइप कॉलम पेश करने की आवश्यकता होगी ताकि वे मुख्य तालिका को इंगित करने वाली विदेशी कुंजी प्राप्त कर सकें, और उस बिंदु पर आप प्रत्येक सहायक तालिका में चेक बाधा जोड़ सकते हैं जिसके लिए प्रकार सही होना आवश्यक है। इस तरह:

create table Product (
    type char(1) not null check (type in ('B', 'M', 'V')), 
    id integer not null, 
    name varchar(255) not null, 
    primary key (type, id) 
); 

create table Book (
    type char(1) not null check (type = 'B'), 
    id integer not null, 
    number_of_pages integer not null, 
    primary key (type, id), 
    foreign key (type, id) references Product 
); 

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

हालांकि, किसी भी सहायक तालिका में संबंधित पंक्तियों के बिना मुख्य तालिका में पंक्तियां बनाना अभी भी संभव है। मुझे पता नहीं है कि इसे कैसे ठीक किया जाए।

स्तंभों के दोहराव की एक संभावित समस्या भी है - जैसा ऊपर की स्कीमा में है, जहां अवधि कॉलम दो तालिकाओं में डुप्लिकेट किया गया है। आपको लगता है कि ठीक कर सकते हैं साझा स्तंभों के लिए मध्यवर्ती सहायक टेबल शुरू करने से:

create table Media (
    type char(1) not null check (type in ('M', 'V')), 
    id integer not null, 
    duration_in_seconds integer not null, 
    primary key (type, id), 
    foreign key (type, id) references Product 
); 

create table Music (
    type char(1) not null check (type = 'M'), 
    id integer not null, 
    primary key (type, id), 
    foreign key (type, id) references Product 
); 

create table Video (
    type char(1) not null check (type = 'V'), 
    id integer not null, 
    classification varchar(2) not null check (classification in ('U', 'PG', '12', '15', '18')), 
    primary key (type, id), 
    foreign key (type, id) references Product 
); 

आप नहीं सोच सकते हैं कि अतिरिक्त प्रयास के लायक था। हालांकि, आप क्या कर रहे दो दृष्टिकोण (एकल मेज और सहायक तालिका) मिश्रण है इस तरह की स्थितियों से निपटने के लिए, और उत्पादों में से कुछ इसी तरह के प्रकार के लिए एक साझा तालिका रखने पर विचार हो सकता है:

create table Media (
    type char(1) not null check (type in ('M', 'V')), 
    id integer not null, 
    duration_in_seconds integer not null, 
    classification varchar(2) check (classification in ('U', 'PG', '12', '15', '18')), 
    primary key (type, id), 
    foreign key (type, id) references Product, 
    check ((case when type = 'V' then (classification is not null) else (classification is null) end))) 
); 

कि विशेष रूप से उपयोगी हो सकता है यदि ऐसे ही प्रकार के उत्पाद थे जो आवेदन में एक साथ लम्बे हुए थे। इस उदाहरण में, अगर आपके shopfront पुस्तकों के लिए ऑडियो और वीडियो एक साथ है, लेकिन अलग से प्रस्तुत करता है, तो इस संरचना और अधिक कुशल पुनर्प्राप्ति मीडिया के प्रत्येक प्रकार के लिए अलग सहायक तालिकाओं की तुलना का समर्थन कर सकता है। आपकी सहायता के लिए

+0

धन्यवाद। लेकिन मुझे लगता है कि यह मेरी बहुत मदद नहीं करेगा। – user2455135

+1

ओह ठीक है, यह शर्म की बात है। एक समाधान खोजने के लिए शुभकामनाएँ! –

+0

@ टॉम एंडरसन यह एक आकर्षक और पूर्ण उत्तर है। क्या आप कुछ और जानकारी प्रदान कर सकते हैं कि आप इकाई-विशेषता-मूल्य डिज़ाइन के प्रशंसक क्यों नहीं हैं? धन्यवाद – mils

संबंधित मुद्दे