महाप्रकार / उपप्रकार
कैसे के बारे में supertype / उपप्रकार पैटर्न में देख रहे हो? सामान्य स्तंभ एक मूल तालिका में जाते हैं। प्रत्येक अलग प्रकार की अपनी पीके के रूप में माता-पिता की आईडी के साथ अपनी तालिका होती है और इसमें सभी उपप्रकारों के लिए सामान्य कॉलम नहीं होते हैं। आप यह सुनिश्चित करने के लिए कि प्रत्येक उपकरण एक से अधिक उपप्रकार से अधिक का नहीं हो सकता है, दोनों माता-पिता और बच्चों की तालिकाओं में एक प्रकार का कॉलम शामिल कर सकते हैं। (ItemID, ItemTypeID) पर बच्चों और माता-पिता के बीच एक FK बनाएं। आप वांछित अखंडता को बनाए रखने के लिए FKs का उपयोग या तो सुपरटाइप या उपप्रकार तालिकाओं में कर सकते हैं। उदाहरण के लिए, यदि किसी भी प्रकार के आइटम की अनुमति है, तो मूल तालिका में FK बनाएं। यदि केवल SubItemType1 को संदर्भित किया जा सकता है, तो उस तालिका में FK बनाएं। मैं टाइपिंग को संदर्भित तालिका से बाहर छोड़ दूंगा।
नामकरण
जब नामकरण की बात आती है, तो आपके पास दो विकल्प होते हैं जैसे कि मैं इसे देखता हूं (चूंकि "आईडी" की तीसरी पसंद मेरे दिमाग में एक मजबूत पैटर्न है)। या तो उप-कुंजी कुंजी आइटम को कॉल करें जैसे कि यह मूल तालिका में है, या इसे उप-नाम नाम जैसे डोहिकेयिड कहें। कुछ विचार और इस के साथ कुछ अनुभव के बाद, मैं इसे DoohickeyID कहने की वकालत करता हूं। इसका कारण यह है कि भले ही सबटाइप तालिका के बारे में भ्रम हो सकता है कि वास्तव में आइटम (बजाय Doohickeys) वाले भेस में, यह एक छोटी नकारात्मक है जब आप Doohickey तालिका में एक FK बनाते हैं और स्तंभ नाम नहीं करते हैं। मेल खाते हैं!
EAV करने के लिए EAV या नहीं - EAV डेटाबेस के साथ मेरा अनुभव
यदि ईएवी वही है जो आपको वास्तव में करना है, तो यह वही है जो आपको करना है। लेकिन अगर ऐसा नहीं होता तो आपको क्या करना होता?
मैंने एक ईएवी डेटाबेस बनाया जो एक व्यवसाय में उपयोग में है। भगवान का शुक्र है, डेटा का सेट छोटा है (हालांकि दर्जनों आइटम प्रकार हैं) इसलिए प्रदर्शन खराब नहीं है। लेकिन यह बुरा होगा यदि डेटाबेस में कुछ हजार से अधिक आइटम थे! इसके अतिरिक्त, तालिकाएँ प्रश्न के लिए इतनी कठोर हैं। इस अनुभव ने मुझे भविष्य में यदि संभव हो तो ईएवी डेटाबेस से बचने की इच्छा पैदा की है।
अब, मेरे डेटाबेस में मैंने एक संग्रहीत प्रक्रिया बनाई है जो स्वचालित रूप से मौजूद प्रत्येक उप-प्रकार के लिए PIVOTed विचार बनाता है। मैं बस AutoDoohickey से क्वेरी कर सकता हूं। उपप्रकारों के बारे में मेरी मेटाडेटा में एक "शॉर्टनेम" कॉलम है, जिसमें दृश्य नामों में उपयोग के लिए उपयुक्त ऑब्जेक्ट-सुरक्षित नाम है। मैंने भी विचारों को अपूरणीय बना दिया! दुर्भाग्यवश, आप उन्हें एक अपडेट में शामिल नहीं कर सकते, लेकिन आप उन्हें पहले से मौजूद पंक्ति में सम्मिलित कर सकते हैं, जिसे एक अद्यतन में परिवर्तित किया जाएगा। दुर्भाग्य से, आप केवल कुछ कॉलमों को अपडेट नहीं कर सकते हैं, क्योंकि INSERT-to-UPDATE रूपांतरण प्रक्रिया के साथ आप कौन से कॉलम को अपडेट करना चाहते हैं, इसका संकेत देने का कोई तरीका नहीं है: एक NULL मान ऐसा लगता है कि "इस कॉलम को NULL में अपडेट करें" भले ही आप यह इंगित करना चाहते हैं कि "इस कॉलम को बिल्कुल भी अपडेट न करें।"
ईएवी डेटाबेस को उपयोग करना आसान बनाने के लिए इस सभी सजावट के बावजूद, मैं अभी भी इन विचारों का उपयोग सबसे सामान्य क्वेरी में नहीं करता हूं क्योंकि यह धीमी है। क्वेरी की शर्तों को सभी तरह से Value
मेज पर वापस धकेल दिया नहीं जाता है , इसलिए इसे फ़िल्टर करने से पहले उस दृश्य के प्रकार की सभी वस्तुओं का एक मध्यवर्ती परिणाम सेट करना होगा। आउच। इसलिए मेरे पास कई, कई के साथ कई प्रश्न हैं, कई जुड़ते हैं, प्रत्येक एक अलग मूल्य और इतने पर बाहर निकलने के लिए। वे अपेक्षाकृत अच्छा प्रदर्शन करते हैं, लेकिन ouch! यहाँ एक उदाहरण है। SP जो इसे बनाता है (और इसका अद्यतन ट्रिगर) एक विशाल जानवर है, और मुझे इस पर गर्व है, लेकिन यह ऐसा कुछ नहीं है जिसे आप कभी बनाए रखने की कोशिश करना चाहते हैं।
CREATE VIEW [dbo].[AutoModule]
AS
--This view is automatically generated by the stored procedure AutoViewCreate
SELECT
ElementID,
ElementTypeID,
Convert(nvarchar(160), [3]) [FullName],
Convert(nvarchar(1024), [435]) [Descr],
Convert(nvarchar(255), [439]) [Comment],
Convert(bit, [438]) [MissionCritical],
Convert(int, [464]) [SupportGroup],
Convert(int, [461]) [SupportHours],
Convert(nvarchar(40), [4]) [Ver],
Convert(bit, [28744]) [UsesJava],
Convert(nvarchar(256), [28745]) [JavaVersions],
Convert(bit, [28746]) [UsesIE],
Convert(nvarchar(256), [28747]) [IEVersions],
Convert(bit, [28748]) [UsesAcrobat],
Convert(nvarchar(256), [28749]) [AcrobatVersions],
Convert(bit, [28794]) [UsesDotNet],
Convert(nvarchar(256), [28795]) [DotNetVersions],
Convert(bit, [512]) [WebApplication],
Convert(nvarchar(10), [433]) [IFAbbrev],
Convert(int, [437]) [DataID],
Convert(nvarchar(1000), [463]) [Notes],
Convert(nvarchar(512), [523]) [DataDescription],
Convert(nvarchar(256), [27991]) [SpecialNote],
Convert(bit, [28932]) [Inactive],
Convert(int, [29992]) [PatchTestedBy]
FROM (
SELECT
E.ElementID + 0 ElementID,
E.ElementTypeID,
V.AttrID,
V.Value
FROM
dbo.Element E
LEFT JOIN dbo.Value V ON E.ElementID = V.ElementID
WHERE
EXISTS (
SELECT *
FROM dbo.LayoutUsage L
WHERE
E.ElementTypeID = L.ElementTypeID
AND L.AttrLayoutID = 7
)
) X
PIVOT (
Max(Value)
FOR AttrID IN ([3], [435], [439], [438], [464], [461], [4], [28744], [28745], [28746], [28747], [28748], [28749], [28794], [28795], [512], [433], [437], [463], [523], [27991], [28932], [29992])
) P;
यहाँ विशेष मेटाडेटा से किसी अन्य संग्रहीत कार्यविधि द्वारा बनाई गई स्वचालित रूप से निर्मित दृश्य है, उन वस्तुओं के बीच संबंधों को खोजने में मदद करने के लिए जिनके बीच कई रास्ते हो सकते हैं (विशेष रूप से: मॉड्यूल-> सर्वर, मॉड्यूल-> क्लस्टर-> सर्वर, मॉड्यूल- DBMS- > सर्वर, मॉड्यूल-> DBMS-> क्लस्टर-> सर्वर):
CREATE VIEW [dbo].[Link_Module_Server]
AS
-- This view is automatically generated by the stored procedure LinkViewCreate
SELECT
ModuleID = A.ElementID,
ServerID = B.ElementID
FROM
Element A
INNER JOIN Element B
ON EXISTS (
SELECT *
FROM
dbo.Element R1
WHERE
A.ElementID = R1.ElementID1
AND B.ElementID = R1.ElementID2
AND R1.ElementTypeID = 38
) OR EXISTS (
SELECT *
FROM
dbo.Element R1
INNER JOIN dbo.Element R2 ON R1.ElementID2 = R2.ElementID1
WHERE
A.ElementID = R1.ElementID1
AND R1.ElementTypeID = 40
AND B.ElementID = R2.ElementID2
AND R2.ElementTypeID = 38
) OR EXISTS (
SELECT *
FROM
dbo.Element R1
INNER JOIN dbo.Element R2 ON R1.ElementID2 = R2.ElementID1
WHERE
A.ElementID = R1.ElementID1
AND R1.ElementTypeID = 38
AND B.ElementID = R2.ElementID2
AND R2.ElementTypeID = 3122
) OR EXISTS (
SELECT *
FROM
dbo.Element R1
INNER JOIN dbo.Element R2 ON R1.ElementID2 = R2.ElementID1
INNER JOIN dbo.Element C2 ON R2.ElementID2 = C2.ElementID
INNER JOIN dbo.Element R3 ON R2.ElementID2 = R3.ElementID1
WHERE
A.ElementID = R1.ElementID1
AND R1.ElementTypeID = 40
AND C2.ElementTypeID = 3080
AND R2.ElementTypeID = 38
AND B.ElementID = R3.ElementID2
AND R3.ElementTypeID = 3122
)
WHERE
A.ElementTypeID = 9
AND B.ElementTypeID = 17
हाइब्रिड दृष्टिकोण
यदि आपके पास EAV डेटाबेस के कुछ गतिशील पहलू हैं, तो आप मेटाडेटा बनाने पर विचार कर सकते हैं जैसे कि आपके पास इस तरह का डेटाबेस था, बल्कि वास्तव में supertype / subtype design pattern का उपयोग कर रहा था। हां, आपको नई तालिकाएँ बनानी होंगी, और कॉलम जोड़ने और हटाने और संशोधित करने होंगे। लेकिन उचित पूर्व प्रसंस्करण के साथ (जैसे मैंने अपने ईएवी डेटाबेस के ऑटो विचारों के साथ किया था) आपके पास काम करने के लिए वास्तविक टेबल जैसी वस्तुएं हो सकती हैं। केवल, वे मेरे जैसे ही नहीं होते हैं और क्वेरी ऑप्टिमाइज़र बेस टेबल पर नीचे जा सकते हैं (पढ़ें: उनके साथ अच्छा प्रदर्शन करें)। सुपरटेप टेबल और सबटाइप टेबल के बीच एक जुड़ाव होगा। आपका एप्लिकेशन मेटाडेटा को पढ़ने के लिए सेट किया जा सकता है ताकि यह पता चल सके कि यह क्या करना है (या यह कुछ मामलों में ऑटो-जनरेट किए गए विचारों का उपयोग कर सकता है)।
या, यदि आपके पास उप-प्रकारों का एक बहु-स्तरीय सेट था, तो बस कुछ जुड़ता है। बहु-स्तरीय से मेरा मतलब है कि जब कुछ उपप्रकार सामान्य कॉलम साझा करते हैं, लेकिन सभी नहीं, तो आप उन लोगों के लिए एक उपप्रकार तालिका रख सकते हैं जो स्वयं कुछ अन्य तालिकाओं का एक सुपरटेप है। उदाहरण के लिए, यदि आप सर्वर, राउटर, और प्रिंटर के बारे में जानकारी संग्रहीत कर रहे हैं, तो "आईपी डिवाइस" का एक मध्यवर्ती उपप्रकार समझ में आ सकता है।
मैं चेतावनी दूंगा कि मैंने अभी तक इस तरह के हाइब्रिड सुपरटेप / उपप्रकार ईएवी-मेटाबेलेटी-डेकोरेटेड डेटाबेस को नहीं बनाया है, जैसे कि मैं यहां सुझाव दे रहा हूं कि वास्तविक दुनिया में कोशिश करना अभी बाकी है। लेकिन ईएवी के साथ मैंने जो समस्याएं अनुभव की हैं, वे छोटी नहीं हैं, और कुछ करना संभवत: एक पूर्ण आवश्यक है यदि आपका डेटाबेस बड़ा होने वाला है और आप कुछ पागल महंगे विशाल हार्डवेयर के बिना अच्छा प्रदर्शन चाहते हैं।
मेरी राय में, वास्तविक उपप्रकार तालिकाओं के उपयोग / निर्माण / संशोधन को स्वचालित करने में बिताया गया समय अंततः सबसे अच्छा होगा। डेटा द्वारा संचालित लचीलेपन पर ध्यान केंद्रित करने से ईएवी ध्वनि इतनी आकर्षक हो जाती है (और मुझे विश्वास है कि मैं कैसे प्यार करता हूं जब कोई व्यक्ति मुझसे एक तत्व प्रकार पर एक नई विशेषता के लिए पूछता है मैं इसे लगभग 18 सेकंड में जोड़ सकता हूं और वे तुरंत वेब साइट पर डेटा दर्ज करना शुरू कर सकते हैं )। लेकिन लचीलेपन को एक से अधिक तरीकों से पूरा किया जा सकता है! प्री-प्रोसेसिंग इसे करने का एक और तरीका है। यह इतनी शक्तिशाली विधि है कि बहुत कम लोग उपयोग करते हैं, पूरी तरह से डेटा-संचालित होने का लाभ देते हैं लेकिन हार्ड-कोडेड होने का प्रदर्शन करते हैं।
(नोट: हाँ उन विचारों को वास्तव में इस तरह स्वरूपित किया गया है और PIVOT वाले वास्तव में अपडेट ट्रिगर करते हैं। :) यदि कोई वास्तव में है जो लंबे और जटिल UPDATE ट्रिगर के भयानक दर्दनाक विवरणों में रुचि रखता है, तो मुझे बताएं और मैं पोस्ट करूंगा आप के लिए एक नमूना है।)
और वन मोर आइडिया
अपना सारा डेटा एक तालिका में रखें। स्तंभों को सामान्य नाम दें और फिर कई उद्देश्यों के लिए उनका पुन: उपयोग / दुरुपयोग करें। उन्हें समझदार नाम देने के लिए इन पर विचार बनाएं। उपयुक्त डेटा-प्रकार अप्रयुक्त स्तंभ उपलब्ध नहीं होने पर कॉलम जोड़ें और अपने विचारों को अपडेट करें। सबटाइप / सुपरपाइप के बारे में मेरी लंबाई के बावजूद, यह सबसे अच्छा तरीका हो सकता है।