संशोधन के लिए डेटाबेस डिजाइन


125

डेटाबेस में संस्थाओं के लिए सभी संशोधनों (चेंज हिस्ट्री) को स्टोर करने के लिए हमें प्रोजेक्ट की आवश्यकता है। वर्तमान में हमारे पास इसके लिए 2 डिज़ाइन किए गए प्रस्ताव हैं:

जैसे "कर्मचारी" इकाई

डिजाइन 1:

-- Holds Employee Entity
"Employees (EmployeeId, FirstName, LastName, DepartmentId, .., ..)"

-- Holds the Employee Revisions in Xml. The RevisionXML will contain
-- all data of that particular EmployeeId
"EmployeeHistories (EmployeeId, DateModified, RevisionXML)"

डिजाइन 2:

-- Holds Employee Entity
"Employees (EmployeeId, FirstName, LastName, DepartmentId, .., ..)"

-- In this approach we have basically duplicated all the fields on Employees 
-- in the EmployeeHistories and storing the revision data.
"EmployeeHistories (EmployeeId, RevisionId, DateModified, FirstName, 
      LastName, DepartmentId, .., ..)"

क्या इस काम को करने का कोई और तरीका है?

"डिज़ाइन 1" के साथ समस्या यह है कि हमें हर बार XML को पार्स करना पड़ता है जब आपको डेटा एक्सेस करने की आवश्यकता होती है। यह प्रक्रिया को धीमा कर देगा और कुछ सीमाएं भी जोड़ देगा जैसे हम संशोधन डेटा फ़ील्ड में जुड़ नहीं सकते।

और "डिजाइन 2" के साथ समस्या यह है कि हमें सभी संस्थाओं पर प्रत्येक और हर क्षेत्र को डुप्लिकेट करना होगा (हमारे पास लगभग 70-80 इकाइयां हैं जिनके लिए हम संशोधन करना चाहते हैं)।



1
FYI करें: अगर यह मदद कर सकता है तो बस .Sql सर्वर 2008 और इसके बाद के संस्करण की तकनीक है जो टेबल पर परिवर्तनों के इतिहास को दर्शाती है..विशेष-talk.com/sql/learn-sql-server/… अधिक जानने के लिए और मुझे यकीन है कि डीबी जैसे ओरेकल में भी कुछ ऐसा होगा।
दुरई अमूथन।

ध्यान रखें कि कुछ कॉलम XML या JSON को स्वयं स्टोर कर सकते हैं। यदि अब ऐसा नहीं होता है तो भविष्य में ऐसा हो सकता है। बेहतर सुनिश्चित करें कि आपको इस तरह के डेटा को दूसरे में घोंसला बनाने की आवश्यकता नहीं है।
जकुबिसजॉन १४'१

जवाबों:


38
  1. है यह सब एक तालिका में एक IsCurrent discriminator विशेषता के साथ डाल दिया। यह बस लाइन की समस्याओं का कारण बनता है, सरोगेट कुंजी और अन्य सभी प्रकार की समस्याओं की आवश्यकता होती है।
  2. स्कीमा 2 में स्कीमा परिवर्तन की समस्या है। यदि आप एम्प्लॉइज टेबल बदलते हैं तो आपको एंप्लॉयीज टेबल और उसके साथ जाने वाले सभी संबंधित स्प्रोस को बदलना होगा। संभावित रूप से आप स्कीमा परिवर्तन के प्रयास को दोगुना करते हैं।
  3. डिजाइन 1 अच्छी तरह से काम करता है और यदि ठीक से किया जाता है तो प्रदर्शन हिट के मामले में ज्यादा खर्च नहीं होता है। संभावित प्रदर्शन समस्याओं को प्राप्त करने के लिए आप एक xml स्कीमा और यहां तक ​​कि अनुक्रमित का उपयोग कर सकते हैं। Xml को पार्स करने के बारे में आपकी टिप्पणी मान्य है लेकिन आप आसानी से xquery का उपयोग करके एक दृश्य बना सकते हैं - जिसे आप प्रश्नों में शामिल कर सकते हैं और इसमें शामिल हो सकते हैं। कुछ इस तरह...
CREATE VIEW EmployeeHistory
AS
, FirstName, , DepartmentId

SELECT EmployeeId, RevisionXML.value('(/employee/FirstName)[1]', 'varchar(50)') AS FirstName,

  RevisionXML.value('(/employee/LastName)[1]', 'varchar(100)') AS LastName,

  RevisionXML.value('(/employee/DepartmentId)[1]', 'integer') AS DepartmentId,

FROM EmployeeHistories 

25
आप यह क्यों कहते हैं कि यह सब एक तालिका में IsCurrent ट्रिगर के साथ संग्रहीत नहीं है। क्या आप मुझे कुछ उदाहरणों की ओर संकेत कर सकते हैं जहाँ यह समस्याग्रस्त होगा।
नाथन डब्ल्यू

@ साइमन मुनरो एक प्राथमिक कुंजी या संकुल कुंजी के बारे में क्या? खोज को तेज़ बनाने के लिए हम डिज़ाइन 1 इतिहास तालिका में कौन सी कुंजी जोड़ सकते हैं?
गत

मैं SELECT * FROM EmployeeHistory WHERE LastName = 'Doe'एक पूर्ण तालिका स्कैन में एक सरल परिणाम मानता हूं । किसी एप्लिकेशन को स्केल करने के लिए सबसे अच्छा विचार नहीं है।
काई

54

मुझे लगता है कि यहाँ पूछने वाला महत्वपूर्ण प्रश्न है 'कौन / कौन इतिहास का उपयोग करने जा रहा है'?

अगर यह ज्यादातर रिपोर्टिंग / मानव पठनीय इतिहास के लिए होने जा रहा है, तो हमने इस योजना को अतीत में लागू किया है ...

'ऑडिटट्राइल' नामक एक टेबल बनाएं या कुछ ऐसा जिसमें निम्नलिखित फ़ील्ड हों ...

[ID] [int] IDENTITY(1,1) NOT NULL,
[UserID] [int] NULL,
[EventDate] [datetime] NOT NULL,
[TableName] [varchar](50) NOT NULL,
[RecordID] [varchar](20) NOT NULL,
[FieldName] [varchar](50) NULL,
[OldValue] [varchar](5000) NULL,
[NewValue] [varchar](5000) NULL

इसके बाद आप अपने सभी तालिकाओं में 'लास्टअपडेटेड यूयूज़रआईडी' कॉलम जोड़ सकते हैं, जिसे हर बार जब आप टेबल पर अपडेट / इंसर्ट करते हैं, तो सेट किया जाना चाहिए।

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

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

मुझे यकीन है कि इस प्रणाली में कमियां हो सकती हैं - भारी अपडेट किए गए डेटाबेस के लिए प्रदर्शन प्रभावित हो सकता है, लेकिन मेरे वेब-ऐप के लिए, हमें लिखने की तुलना में कई अधिक रीड मिलते हैं और ऐसा लगता है कि यह बहुत अच्छा प्रदर्शन कर रहा है। हमने टेबल परिभाषाओं के आधार पर ट्रिगर्स को स्वचालित रूप से लिखने के लिए थोड़ी VB.NET उपयोगिता भी लिखी।

सिर्फ एक विचार!


5
NewValue को स्टोर करने की आवश्यकता नहीं है, क्योंकि यह ऑडिट टेबल में संग्रहीत है।
पेट्रस थेरॉन

17
सख्ती से, यह सच है। लेकिन - जब एक ही समय में एक ही फ़ील्ड में कई परिवर्तन होते हैं, तो नए मान को संग्रहीत करने से प्रश्न बनते हैं जैसे कि 'मुझे ब्रायन द्वारा किए गए सभी परिवर्तन दिखाएं' इतना आसान है क्योंकि एक अपडेट के बारे में सभी जानकारी में रखी गई है एक रिकॉर्ड। सिर्फ एक विचार!
क्रिस रॉबर्ट्स

1
मुझे लगता है कि sysnameतालिका और स्तंभ नामों के लिए अधिक उपयुक्त डेटा प्रकार हो सकता है।
सैम

2
@ Sysname का उपयोग करके कोई मान नहीं जोड़ा जाता है; यह भी भ्रामक हो सकता है ... stackoverflow.com/questions/5720212/…
जोवेन

19

इतिहास टेबल्स में लेख डेटाबेस प्रोग्रामर ब्लॉग उपयोगी हो सकता है - को शामिल किया गया अंक में से कुछ यहां उठाए गए और डेल्टा के भंडारण की चर्चा।

संपादित करें

में इतिहास टेबल्स निबंध, लेखक ( केनेथ डाउंस ), कम से कम सात कॉलम की एक इतिहास तालिका को बनाए रखने की सिफारिश की:

  1. बदलाव का टाइमस्टैम्प,
  2. उपयोगकर्ता जिसने परिवर्तन किया,
  3. परिवर्तित किए गए रिकॉर्ड की पहचान करने के लिए एक टोकन (जहां इतिहास को वर्तमान स्थिति से अलग रखा गया है),
  4. क्या परिवर्तन एक सम्मिलित, अद्यतन या हटाना था,
  5. पुराना मान,
  6. नया मूल्य,
  7. डेल्टा (संख्यात्मक मूल्यों में परिवर्तन के लिए)।

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

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


14

हमने क्रिस रॉबर्ट्स ने जो समाधान सुझाया है, उसके समान हमने एक समाधान लागू किया है और यह हमारे लिए बहुत अच्छा काम करता है।

केवल अंतर यह है कि हम केवल नए मूल्य को संग्रहीत करते हैं। पुराना मूल्य पिछली इतिहास पंक्ति में संग्रहीत होने के बाद है

[ID] [int] IDENTITY(1,1) NOT NULL,
[UserID] [int] NULL,
[EventDate] [datetime] NOT NULL,
[TableName] [varchar](50) NOT NULL,
[RecordID] [varchar](20) NOT NULL,
[FieldName] [varchar](50) NULL,
[NewValue] [varchar](5000) NULL

कहते हैं कि आपके पास 20 स्तंभों वाली एक तालिका है। इस तरह आपको केवल सटीक कॉलम को स्टोर करना होगा जो पूरी पंक्ति को संग्रहीत करने के बजाय बदल गया है।


14

डिजाइन 1 से बचें; एक बार यह बहुत आसान नहीं है, उदाहरण के लिए आपको रिकॉर्ड के पुराने संस्करणों में रोलबैक करने की आवश्यकता होगी - या तो व्यवस्थापक कंसोल का उपयोग करके स्वचालित रूप से या "मैन्युअल रूप से"।

मुझे वास्तव में डिज़ाइन 2 के नुकसान नहीं दिख रहे हैं। मुझे लगता है कि दूसरा, इतिहास तालिका में पहले, रिकॉर्ड्स तालिका में मौजूद सभी कॉलम होने चाहिए। उदाहरण के लिए mysql में आप आसानी से एक ही तालिका ( create table X like Y) के समान संरचना के साथ तालिका बना सकते हैं । और, जब आप अपने लाइव डेटाबेस में रिकॉर्ड्स टेबल की संरचना को बदलने वाले होते हैं, तो आपको alter tableवैसे भी कमांड का उपयोग करना होगा - और इन कमांड्स को आपके हिस्ट्री टेबल के लिए चलाने में कोई बड़ा प्रयास नहीं है।

टिप्पणियाँ

  • रिकॉर्ड तालिका में केवल नवीनतम संशोधन शामिल हैं;
  • इतिहास तालिका में रिकॉर्ड तालिका में पिछले सभी संशोधन शामिल हैं;
  • इतिहास तालिका की प्राथमिक कुंजी रिकॉर्ड RevisionIdस्तंभ के साथ रिकॉर्ड तालिका की प्राथमिक कुंजी है ;
  • अतिरिक्त सहायक फ़ील्ड के बारे में सोचें जैसे ModifiedBy- उपयोगकर्ता जो विशेष संशोधन बनाए। आप यह भी DeletedByट्रैक करना चाह सकते हैं कि किसने विशेष संशोधन को हटाया है।
  • इस बारे में सोचें कि क्या DateModifiedमतलब होना चाहिए - या तो इसका मतलब है कि यह विशेष संशोधन कहाँ बनाया गया था, या इसका मतलब यह होगा कि जब इस विशेष संशोधन को किसी अन्य द्वारा बदल दिया गया था। पूर्व को रिकॉर्ड तालिका में फ़ील्ड की आवश्यकता होती है, और पहली नज़र में यह अधिक सहज लगता है; दूसरा समाधान हालांकि हटाए गए अभिलेखों के लिए अधिक व्यावहारिक प्रतीत होता है (दिनांक जब यह विशेष संशोधन हटा दिया गया था)। यदि आप पहले समाधान के लिए जाते हैं, तो आपको संभवतः एक दूसरे क्षेत्र की आवश्यकता होगी DateDeleted(केवल अगर आपको इसकी आवश्यकता है)। आप पर निर्भर करता है और आप वास्तव में क्या रिकॉर्ड करना चाहते हैं।

डिजाइन 2 में संचालन बहुत तुच्छ हैं:

संशोधित
  • रिकॉर्ड्स टेबल से हिस्ट्री टेबल पर रिकॉर्ड कॉपी करें, इसे नया रिविजन करें (यदि यह पहले से रिकॉर्ड टेबल में मौजूद नहीं है), DateModified को हैंडल करें (यह निर्भर करता है कि आप इसकी व्याख्या कैसे करते हैं, ऊपर नोट देखें)
  • रिकॉर्ड्स तालिका में रिकॉर्ड के सामान्य अद्यतन के साथ चलते हैं
हटाएं
  • ठीक उसी तरह से करें जैसे ऑपरेशन को संशोधित करने के पहले चरण में। आपके द्वारा चुनी गई व्याख्या के आधार पर, तदनुसार DateModified / DateDeleted को संभालें।
हटाना रद्द करें (या रोलबैक)
  • इतिहास तालिका से सबसे अधिक (या कुछ विशेष?) संशोधन करें और इसे रिकॉर्ड तालिका में कॉपी करें
विशेष रिकॉर्ड के लिए सूची संशोधन इतिहास
  • इतिहास तालिका और अभिलेख तालिका से चयन करें
  • सोचें कि आप इस ऑपरेशन से क्या उम्मीद करते हैं; यह संभवत: यह निर्धारित करेगा कि आपको DateModified / DateDeleted फ़ील्ड्स से क्या जानकारी चाहिए (ऊपर नोट देखें)

यदि आप Design 2 के लिए जाते हैं, तो सभी SQL कमांड्स को करने की आवश्यकता है जो बहुत आसान है, साथ ही रखरखाव भी! हो सकता है, यह बहुत आसान हो जाएगा यदि आप सहायक स्तंभों ( RevisionId, DateModified) का उपयोग रिकॉर्ड्स तालिका में भी करते हैं - दोनों तालिकाओं को बिल्कुल समान संरचना (अद्वितीय कुंजियों को छोड़कर) पर रखने के लिए! यह सरल SQL कमांड के लिए अनुमति देगा, जो किसी भी डेटा संरचना परिवर्तन के प्रति सहनशील होगा:

insert into EmployeeHistory select * from Employe where ID = XX

लेनदेन का उपयोग करने के लिए मत भूलना!

स्केलिंग के लिए , यह समाधान बहुत कुशल है, क्योंकि आप XML के किसी भी डेटा को आगे और पीछे से ट्रांसफॉर्म नहीं करते हैं, बस पूरी टेबल की पंक्तियों को कॉपी करते हैं - बहुत ही सरल प्रश्न, सूचकांकों का उपयोग करते हुए - बहुत कुशल!


12

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

यह एक उपकरण बनाने के लिए काफी सरल है जो एक तालिका के लिए सिस्टम डेटा शब्दकोश को पढ़ेगा और एक स्क्रिप्ट उत्पन्न करेगा जो इसे बनाने के लिए छाया तालिका और ट्रिगर का एक सेट बनाता है।

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


3
सादगी के लिए +1! कुछ लोग बाद के बदलावों के डर से ओवर-इंजीनियर हो जाएंगे, जबकि अधिकांश समय वास्तव में कोई परिवर्तन नहीं होता है! इसके अतिरिक्त, एक तालिका में इतिहास को प्रबंधित करना बहुत आसान है और कुछ झंडे या स्थिति के साथ एक तालिका (दुःस्वप्न) में उन सभी को छोड़कर अन्य अभिलेखों में वास्तविक रिकॉर्ड। यह KISS 'कहा जाता है और सामान्य रूप से लंबे समय में आपको पुरस्कृत करेगा है।
5

+1 पूरी तरह से सहमत हूं, वास्तव में मैं अपने उत्तर में क्या कहता हूं ! सरल और शक्तिशाली!
टीएमएस

8

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

Employee (Id, Name, ... , IsActive)  

जहाँ IsActive नवीनतम संस्करण का संकेत है

यदि आप कुछ अतिरिक्त जानकारी को संशोधन के साथ जोड़ना चाहते हैं, तो आप उस जानकारी से युक्त एक अलग तालिका बना सकते हैं और इसे PK \ FK संबंध का उपयोग करके इकाई तालिकाओं के साथ जोड़ सकते हैं।

इस तरह आप कर्मचारियों के सभी संस्करण को एक तालिका में संग्रहीत कर सकते हैं। इस दृष्टिकोण के पेशेवरों:

  • सरल डेटा बेस संरचना
  • तालिका के बाद से कोई संघर्ष केवल अपेंडेंस नहीं बन जाता है
  • आप बस IsActive ध्वज को बदलकर पिछले संस्करण में रोलबैक कर सकते हैं
  • ऑब्जेक्ट हिस्ट्री पाने के लिए जॉइन की जरूरत नहीं है

ध्यान दें कि आपको प्राथमिक कुंजी को गैर अद्वितीय होने की अनुमति देनी चाहिए।


6
मैं IsActive के अलावा या इसके बजाय एक "RevisionNumber" या "RevisionDate" कॉलम का उपयोग करूंगा, ताकि आप क्रम में सभी संशोधन देख सकें।
स्किलिविज़

मैं एक "parentRowId" का उपयोग करूंगा क्योंकि यह आपको पिछले संस्करणों के साथ-साथ आधार और अंत दोनों को जल्दी से खोजने की क्षमता प्रदान करता है।
chacham15

6

जिस तरह से मैंने इसे अतीत में देखा है वह है

Employees (EmployeeId, DateModified, < Employee Fields > , boolean isCurrent );

आप इस तालिका पर "अपडेट" कभी नहीं करते (केवल समवर्ती के वैध को छोड़कर), बस नई पंक्तियाँ डालें। किसी भी कर्मचारी के लिए, केवल 1 पंक्ति में समवर्ती == 1 हो सकता है।

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

यह विधि ठीक है, लेकिन आप कुछ जटिल प्रश्नों को समाप्त कर सकते हैं।

निजी तौर पर, मुझे आपके डिज़ाइन 2 के बहुत अच्छे तरीके से करने का शौक है, जो कि मैंने इसे अतीत में भी किया है। समझने में सरल, लागू करने के लिए सरल और बनाए रखने के लिए सरल है।

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

इतिहास तालिकाओं और ट्रिगर्स के निर्माण को स्वचालित बनाए रखना काफी आसान होगा (यह मानते हुए कि यह ट्रिगर्स के माध्यम से किया जाएगा)।


4

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


4

मैं आपके साथ अपना डिज़ाइन साझा करने जा रहा हूं और यह आपके दोनों डिज़ाइनों से अलग है, इसमें प्रत्येक इकाई के प्रकार के लिए एक टेबल की आवश्यकता है। मुझे किसी भी डेटाबेस डिज़ाइन का वर्णन करने का सबसे अच्छा तरीका मिला है वह है ERD, यहाँ मेरा है:

यहाँ छवि विवरण दर्ज करें

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

दो फील्ड्स का Unit_id और revision_id

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

वहां भी एक राज्य क्षेत्र के अंदर है_ परिशोधन तालिका जो संशोधन की स्थिति का संकेत देती है। यह तीन राज्यों में से एक हो सकता है: latest, obsoleteयाdeleted (संशोधन की तारीख पर भरोसा नहीं करना आपके प्रश्नों को बढ़ावा देने में बहुत मदद करता है)।

Revision_id पर एक अंतिम नोट, मैंने एक विदेशी कुंजी कनेक्ट करने के लिए कर्मचारी_id को revision_id में नहीं बनाया क्योंकि हम प्रत्येक इकाई प्रकार के लिए Unit_revision तालिका को बदलना नहीं चाहते हैं जिसे हम भविष्य में जोड़ सकते हैं।

प्रविष्टि

प्रत्येक कर्मचारी के लिए जिसे आप डेटाबेस में सम्मिलित करना चाहते हैं, आप इकाई और Unit_revision में एक रिकॉर्ड भी जोड़ देंगे । ये पिछले दो रिकॉर्ड आपको किसके द्वारा और कब एक रिकॉर्ड डेटाबेस में डाले गए हैं, इस पर नज़र रखने में मदद करेंगे।

अपडेट करें

मौजूदा कर्मचारी रिकॉर्ड के लिए प्रत्येक अपडेट को दो आवेषण के रूप में लागू किया जाएगा, एक कर्मचारी तालिका में और एक एंट्री_रेविजन में। दूसरा व्यक्ति आपको यह जानने में मदद करेगा कि रिकॉर्ड किसने और कब अपडेट किया है।

विलोपन

किसी कर्मचारी को हटाने के लिए, एक रिकॉर्ड हटा दिया जाता है और किया गया।

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

[अपडेट करें]

नए MySQL संस्करणों में समर्थित विभाजन होने के बाद, मेरा मानना ​​है कि मेरा डिज़ाइन भी सर्वश्रेष्ठ प्रदर्शनों में से एक है। एक अपने क्षेत्र का उपयोग करते हुए विभाजन का उपयोग entityकरके तालिका का typeविभाजन entity_revisionकर सकता है state। यह SELECTडिजाइन को सरल और साफ रखने के लिए दूर तक प्रश्नों को बढ़ावा देगा ।


3

अगर वास्तव में एक ऑडिट ट्रेल की जरूरत है, तो मैं ऑडिट टेबल सॉल्यूशन की ओर झुक जाऊंगा (अन्य टेबलों पर महत्वपूर्ण कॉलम की डिनरलाइज्ड कॉपियों के साथ पूर्ण, जैसे UserName)। हालांकि, ध्यान रखें कि यह कड़वा अनुभव इंगित करता है कि एक एकल ऑडिट टेबल सड़क के नीचे एक बड़ी अड़चन होगी; यह संभवतः आपके सभी अंकेक्षित तालिकाओं के लिए व्यक्तिगत ऑडिट टेबल बनाने के प्रयास के लायक है।

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


3

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

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

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


2

कैसा रहेगा:

  • कर्मचारी कामतत्व
  • तिथि संशोधित
    • और / या संशोधन संख्या, इस पर निर्भर करता है कि आप इसे कैसे ट्रैक करना चाहते हैं
  • ModifiedByUSerId
    • साथ ही कोई अन्य जानकारी जिसे आप ट्रैक करना चाहते हैं
  • कर्मचारी खेतों

आप प्राथमिक कुंजी (EmployeeId, DateModified) बनाते हैं, और प्रत्येक कर्मचारी के लिए "Current" रिकॉर्ड (s) प्राप्त करने के लिए आप बस MAX (DateModified) का चयन करते हैं। IsCurrent का भंडारण करना एक बहुत बुरा विचार है, क्योंकि सबसे पहले, इसकी गणना की जा सकती है, और दूसरी बात, डेटा के लिए सिंक से बाहर निकलना भी बहुत आसान है।

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


इस दृष्टिकोण के बारे में एक कमी यह है कि यदि आप दो तालिकाओं का उपयोग करते हैं तो तालिका अधिक तेज़ी से बढ़ेगी।
cdmckay

2

यदि आप इतिहास डेटा (रिपोर्टिंग कारणों के लिए) पर भरोसा करना चाहते हैं, तो आपको संरचना का उपयोग कुछ इस तरह करना चाहिए:

// Holds Employee Entity
"Employees (EmployeeId, FirstName, LastName, DepartmentId, .., ..)"

// Holds the Employee revisions in rows.
"EmployeeHistories (HistoryId, EmployeeId, DateModified, OldValue, NewValue, FieldName)"

या आवेदन के लिए वैश्विक समाधान:

// Holds Employee Entity
"Employees (EmployeeId, FirstName, LastName, DepartmentId, .., ..)"

// Holds all entities revisions in rows.
"EntityChanges (EntityName, EntityId, DateModified, OldValue, NewValue, FieldName)"

आप अपने संशोधनों को XML में भी सहेज सकते हैं, फिर आपके पास एक संशोधन के लिए केवल एक रिकॉर्ड है। यह इस तरह दिखेगा:

// Holds Employee Entity
"Employees (EmployeeId, FirstName, LastName, DepartmentId, .., ..)"

// Holds all entities revisions in rows.
"EntityChanges (EntityName, EntityId, DateModified, XMLChanges)"

1
बेहतर: इवेंट सोर्सिंग का उपयोग करें :)
dariol

1

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

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

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

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


0

ऐसा लगता है कि आप समय के साथ विशिष्ट संस्थाओं में परिवर्तन को ट्रैक करना चाहते हैं, जैसे आईडी 3, "बॉब", "123 मुख्य सड़क", फिर एक और आईडी 3, "बॉब" "234 एल्म सेंट", और इसी तरह, संक्षेप में सक्षम होने में सक्षम हर पते पर एक संशोधन इतिहास दिखाने के लिए "बॉब" पर है।

ऐसा करने का सबसे अच्छा तरीका है कि प्रत्येक रिकॉर्ड पर "वर्तमान" क्षेत्र है, और (शायद) एक टाइमस्टैम्प या एफके को एक तारीख / समय तालिका के लिए।

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

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

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