2009-04-03 13 views
9

कई डेटाबेसों में, मैं डेटाबेस को डिज़ाइन कर रहा हूं जो प्रत्येक तालिका में पंक्तियों के पिछले संस्करणों का रिकॉर्ड रखना चाहिए।डेटाबेस में इतिहास पंक्ति प्रबंधन

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

नुकसान:

  • (तालिका जरूरतों की संरचना में परिवर्तन के मामले में) 1 के बजाय 2 टेबल,
  • आवेदन टेबल के दोनों बजाय पता करने की जरूरत है के रखरखाव एक की टेबल के
  • नाम तालिका नाम के एक सम्मेलन और इतिहास तालिका नाम (उदाहरण के लिए SOME_TABLE, SOME_TABLE_HIST)

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

  • जब एक पंक्ति तालिका में डाला जाता है, यह IS_LAST = 1 के साथ डाला जाएगा जोड़ें।
  • जब कोई पंक्ति अपडेट हो जाती है, तो मूल पंक्ति की एक प्रति को IS_LAST = 0 के परिवर्तन के साथ उसी तालिका में डुप्लिकेट किया जाएगा, और मूल पंक्ति आवश्यकतानुसार अपडेट हो जाएगी (अभी भी IS_LAST = 1 रखना)।

मान लीजिए कि मेरे मामले में, पंक्तियों को औसतन 10 बार अपडेट किया जाता है। यह भी मानते हैं कि एप्लिकेशन द्वारा किए गए कार्यों का कम से कम 9 0% केवल पंक्तियों के हाल के संस्करण पर होता है।

मेरा डेटाबेस एक "ओरेकल 10 जी है ताकि" सक्रिय "तालिका पतला रखने के लिए, हम तालिका को 2 विभाजनों में विभाजित कर सकते हैं: IS_LAST = 1 विभाजन, और IS_LAST = 0 विभाजन।

समस्या रखने वाले इतिहास डेटा को हल करने का एक अच्छा तरीका विभाजन कर रहा है?

क्या यह समाधान इन तालिकाओं के लिए अन्य विभाजन क्षमता को सीमित करता है?

धन्यवाद!

उत्तर

2

मैं दो टेबल बनाउंगा: एक इस्लास्ट प्रकार के मूल्यों और एक ऐतिहासिक लोगों के लिए। फिर मैं एक ट्रिगर स्थापित करता हूं जो हर बार जब अद्यतन अद्यतन होता है तो ऐतिहासिक तालिका में मूल्य डालता है।

+3

यह ओरेकल है, परेशान क्यों? बस उस कॉलम पर विभाजन करें और पंक्ति माइग्रेशन चालू करें। यह बनाया गया है, दो तालिकाओं को फिर से लिखना और बनाए रखना क्यों। –

0

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

क्या कोई विशेष कारण है कि आप इस स्थिति का सामान्य समाधान नहीं लगाना चाहते हैं?

+0

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

0

आप प्राथमिक कुंजी कैसे परिभाषित करेंगे? एक ही तालिका में इतिहास पंक्तियों को पकड़ने के कारण एक ही प्राथमिक कुंजी के साथ कई पंक्तियां होंगी।

इसके अलावा आपको अपने इतिहास पंक्तियों के क्रम को जानने का कोई तरीका नहीं दिखता है जब एक "असली" पंक्ति एक बार बदल जाती है।

(एक परियोजना मैं पर काम किया है, हम सब इतिहास तालिकाओं उत्पन्न और codesmith का उपयोग कर ट्रिगर, यह बहुत अच्छी तरह से काम किया।)

6

पहला सवाल करना चाहिए हो: क्या आपको लगता है कि डेटा के साथ क्या होगा? यदि आपके पास स्पष्ट व्यावसायिक आवश्यकता नहीं है, तो ऐसा न करें।

मैंने कुछ ऐसा किया और 3 वर्षों के चलने के बाद "वैध डेटा" का लगभग 20% और शेष "पिछले संस्करण" है। और यह 10 मिलियन + 40 मिलियन रिकॉर्ड है। पिछले तीन वर्षों में हमारे पास बदलावों के इतिहास की जांच करने के लिए 2 (दो) अनुरोध थे और दोनों बार अनुरोध मूर्ख थे - हम रिकॉर्ड परिवर्तन के समय टिकट को रिकॉर्ड करते थे और हमें यह जांचने के लिए कहा गया था कि क्या व्यक्ति ओवरटाइम (5 बजे के बाद) काम करते हैं या नहीं।

अब, हम oversized डेटाबेस से फंस गए हैं जिसमें 80% डेटा है जिसे किसी को भी आवश्यकता नहीं है।

संपादित करें:

जब से तुम संभव समाधान के लिए कहा, मैं हम क्या किया व्याख्या करेंगे। यह आपके द्वारा विचार किए जा रहे समाधान से थोड़ा अलग है।

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

हम निम्नलिखित कॉलम के साथ एक संग्रह तालिका में सभी परिवर्तनों को दर्ज:

  • आईडी (किराए की प्राथमिक कुंजी)
  • समय स्टाम्प
  • मूल तालिका
  • मूल रिकॉर्ड
  • की आईडी उपयोगकर्ता आईडी
  • लेनदेन का प्रकार (सम्मिलित करें, अपडेट करें, हटाएं)
  • रिकॉर्ड डेटा के रूप में varchar2 फ़ील्ड
    • यह फ़ील्डनाम/मान जोड़े के रूप में वास्तविक डेटा है।

बात इस तरह से काम करता है:

  • ORM डालने/अद्यतन और comands हटाना है।/आदेशों प्रतिबिंब का उपयोग FIELDNAME/मान युग्म के रूप में स्ट्रिंग बनाने, हटाने
  • हम उस सम्मिलित/अपडेट ओवरराइड करता है और हटाने के आदेशों
    • सम्मिलित/अपडेट करने के लिए हमारे सभी व्यापार वस्तुओं के लिए एक आधार वर्ग बनाया। कोड मैपिंग जानकारी ढूंढता है और फ़ील्ड नाम, संबंधित मान और फ़ील्ड प्रकार पढ़ता है। फिर हम JSON के समान कुछ बनाते हैं (हमने कुछ संशोधन जोड़े)। जब ऑब्जेक्ट की वर्तमान स्थिति का प्रतिनिधित्व करने वाली स्ट्रिंग बनाई जाती है, तो इसे संग्रह तालिका में डाला जाता है।
  • जब नई या अद्यतन ऑब्जेक्ट डेटाबेस तालिका में सहेजी जाती है, तो उसे अपनी लक्षित तालिका में सहेजा जाता है और साथ ही हम संग्रह तालिका में वर्तमान मान के साथ एक रिकॉर्ड डालते हैं।
  • जब वस्तु हटा दी जाती है, तो हम इसे अपने लक्ष्य तालिका से हटा सकते हैं और एक ही समय में हम संग्रह तालिका में एक रिकॉर्ड है कि लेन-देन प्रकार = सम्मिलित "हटाएँ"

प्रो:

  • हम डेटाबेस में प्रत्येक तालिका के लिए संग्रह सारणी नहीं है। जब स्कीमा में परिवर्तन होता है तो हमें संग्रह तालिका को अपडेट करने की चिंता करने की आवश्यकता नहीं होती है।
  • पूरा संग्रह "वर्तमान डेटा" से अलग है, इसलिए संग्रह डेटाबेस पर किसी भी प्रदर्शन हिट को लागू नहीं करता है। हम इसे अलग डिस्क पर अलग टेबल स्पेस पर डालते हैं और यह ठीक काम करता है।
    • सामान्य दर्शक कि संग्रह तालिका सूचीबद्ध कर सकते हैं संग्रह मेज पर फिल्टर के अनुसार:
    • हम संग्रह को देखने के लिए 2 रूपों बनाया। फ़िल्टर डेटा उपयोगकर्ता फॉर्म (समय अवधि, उपयोगकर्ता, ...) पर दर्ज कर सकते हैं। हम फॉर्म रिकॉर्डनाम/मान में प्रत्येक रिकॉर्ड दिखाते हैं और प्रत्येक परिवर्तन रंग कोडित होता है। उपयोगकर्ता प्रत्येक रिकॉर्ड के लिए सभी संस्करण देख सकते हैं और वे देख सकते हैं कि किसने और कब परिवर्तन किए हैं।
    • चालान दर्शक - यह एक जटिल था, लेकिन हमने फ़ॉर्म बनाया जो मूल चालान प्रविष्टि फ़ॉर्म के समान चालान दिखाता है, लेकिन कुछ अतिरिक्त बटन जो विभिन्न पीढ़ियों को दिखा सकते हैं। इस फ़ॉर्म को बनाने के लिए काफी प्रयास हुए। फॉर्म का इस्तेमाल कुछ बार किया गया था और फिर भूल गया क्योंकि वर्तमान वर्कफ़्लो में इसकी आवश्यकता नहीं थी।
  • संग्रह रिकॉर्ड बनाने के लिए कोड एकल सी # कक्षा में स्थित है। डेटाबेस में प्रत्येक तालिका पर ट्रिगर्स की कोई आवश्यकता नहीं है।
  • प्रदर्शन बहुत अच्छा है। चरम समय पर, सिस्टम का उपयोग 700-800 उपयोगकर्ताओं द्वारा किया जाता है। यह एएसपी.Net आवेदन है। एएसपी.Net और ओरेकल दोनों एक दोहरी XEON पर 8 जीबी रैम के साथ चल रहे हैं।

विपक्ष:

  • एकल तालिका संग्रह प्रारूप समाधान की तुलना में पढ़ने के लिए कठिन है जहां डेटा तालिकाओं में से प्रत्येक के लिए एक संग्रह तालिका है।
  • संग्रह तालिका में गैर-आईडी फ़ील्ड पर खोज कठिन है - हम स्ट्रिंग पर केवल LIKE ऑपरेटर का उपयोग कर सकते हैं।

तो, फिर, संग्रह पर आवश्यकताओं की जांच करें। यह मामूली काम नहीं है, लेकिन लाभ और उपयोग न्यूनतम हो सकता है।

+0

लेकिन क्या ओपी की _HIST तालिका है, भले ही डेटाबेस आकार के बारे में तर्क सही न हो? – Learning

+0

@zendar, क्या आप विभाजन का उपयोग करते हैं? – tuinstoel

+0

नहीं। चीजें ठीक तरह से काम करती हैं। यह सिर्फ इतना है कि हमारे पास 5 गुना अधिक रिकॉर्ड होना चाहिए। हमने ऐसा इसलिए किया क्योंकि यह "बहुत महत्वपूर्ण विशेषता" थी जिसे अब किसी को भी जरूरत नहीं है। इसलिए मैंने इसके लिए असफ की प्रेरणा पर सवाल उठाया। शायद वह खुद को कुछ समय और दर्द बचा सकता है। – zendar

0

मैं IS_LAST=1 विभाजन, और IS_LAST=0 विभाजन प्रणाली का उपयोग करूंगा। चूंकि इसे विभाजित किया गया है, यह तेज़ होगा (विभाजन छंटनी) और आपको सामान्य तालिका और इतिहास तालिका के संघ से कभी भी पूछना नहीं होगा।

मैं IS_LAST = 'वाई'/'एन' का उपयोग करूंगा और 1/0 नहीं। 1 और 0 अर्थहीन हैं।

एक विशेष चाल है कि guarrantee मदद कर सकते है कि वहाँ IS_LAST='Y' इकाई प्रति के साथ अधिकतम एक पंक्ति नहीं है: आप एक समारोह है कि रिक्त जब IS_LAST='N' रिटर्न के साथ एक अद्वितीय समारोह आधारित सूचकांक बना सकते हैं और आईडी जब IS_LAST='Y' लौट सकते हैं।यह यहां बताया गया है: http://www.akadia.com/services/ora_function_based_index_1.html

1

यदि मेरे पास रखने के लिए इतिहास के 1 या 2 टेबल हैं तो मैं इसे ठीक कर दूंगा जैसा कि टिंस्टोइल ने सुझाव दिया है। लेकिन अगर आपके पास ऐसा करने के लिए दर्जनों टेबल हैं तो मैं ज़ेंडर द्वारा वर्णित समाधान की ओर बढ़ जाऊंगा। इसका कारण यह है।

कैसे आप निम्न प्रश्नों के उत्तर है,

  • कल से जब सब कुछ ठीक था क्या बदल गया?

  • क्या उपयोगकर्ता SMITHG ने कोई बदलाव किया है?

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

table_name, Column_name, PK, Before_value, After_value, User, timestamp 

आवेषण केवल मूल्यों के बाद,

हटाता है केवल मूल्यों से पहले,

अद्यतन दोनों लेकिन केवल कॉलम जो बदल के लिए की है।

कुछ बदलाव

अगर आप चाहें तो आप इंसर्ट के लिए स्तंभ मान बाहर कर सकते हैं और सिर्फ पी और मैं रिकॉर्ड के बाद से सही मान तालिका में अभी भी कर रहे हैं आप मैं/यू/डी के लिए एक कॉलम शामिल कर सकते हैं।

चूंकि यह ओरेकल है, इसलिए आप table_name पर विभाजन कर सकते हैं, इसलिए संक्षेप में आप वास्तव में प्रति वास्तविक तालिका में एक हिस्ट "टेबल" रखते हैं।

आप आसानी से उपरोक्त प्रश्नों का उत्तर दे सकते हैं, जो मुझे विश्वास है, काफी सरल, अक्सर पूछे जाने वाले प्रश्न। और यह प्रत्येक प्रश्न को नियंत्रित करता है जिसे आप विभाजन या _hist तालिकाओं के साथ उत्तर दे सकते हैं।

0

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

1

चूंकि आप ओरेकल का उपयोग कर रहे हैं, तो आप Oracle Flashback Technology देख सकते हैं। यह डेटा और संरचना दोनों डेटाबेस में सभी परिवर्तनों के परिवर्तन रिकॉर्ड करता है। यह समय टिकट और उपयोगकर्ता नाम भी रिकॉर्ड करता है।

मैंने इसका उपयोग नहीं किया, लेकिन यह सक्षम दिखता है।

+0

यह केवल एक llg सुविधा है, अगर वे उस पर हैं, तो महान, अन्यथा, यह एक विकल्प नहीं है। –

+0

फ्लैशबैक 9i में पेश किया गया है, कुछ 8-9 साल पहले। संस्करण 10 जी में यह काफी परिपक्व हो गया। – zendar

0

यह सब पर निर्भर करता है कि तुम क्या है:

  • आप मानक या एंटरप्राइज़ संस्करण चला रहे हैं? विभाजन केवल एंटरप्राइज़ संस्करण के शीर्ष पर एक विकल्प के रूप में शामिल है। उस here पर अधिक जानकारी।
  • यदि आप एक आसान समाधान ढूंढ रहे हैं जहां आपको अपना कोड बनाए रखने की आवश्यकता नहीं है तो आप इसे करने के लिए Workspace Manager पर जा सकते हैं। हालांकि, मुझे कुछ सीमाएं मिली हैं (उदाहरण के लिए ओरेकल टेक्स्ट इंडेक्स रखरखाव मुश्किल प्रतीत होता है, यदि असंभव नहीं है, हालांकि मैंने इसे केवल 10 जीआर 2 पर देखा है)।
  • अन्यथा, मैं या तो zvolkov के समाधान (इतिहास तालिका में एक ट्रिगर लेखन के साथ लाइव टेबल) या मार्क ब्रैडी के समाधान (परिवर्तन लॉग) के साथ जाना होगा। मैंने दोनों पैटर्न का उपयोग किया है और प्रत्येक के पास इसके पेशेवर और विपक्ष हैं।
  • @zendar: फ्लैशबैक क्वेरी केवल पूर्ववत के लिए काम करती है जैसा आपने पूर्ववत किया है। यह एक दीर्घकालिक समाधान नहीं है, केवल कुछ घंटों में देखने के लिए एक समाधान (आपके द्वारा निर्दिष्ट पूर्ववत प्रतिधारण के आधार पर)।
0

दूसरों के साथ, मैं कस्टम ऑब्जेक्ट & हटाएं विधियों वाले बेस ऑब्जेक्ट के साथ एक ओआरएम (प्रोपेल) का उपयोग करता हूं। ये विधियां मानक सहेजें & को ओवरराइड करती हैं जो ORM के साथ आती हैं। वे यह देखने के लिए जांचते हैं कि कौन से कॉलम बदल गए हैं, और प्रत्येक परिवर्तित कॉलम के लिए परिवर्तन तालिका में 1 पंक्ति बनाएं।

change तालिका के लिए स्कीमा: change_pk, user_fk, user_name, session_id, ip_address, विधि, TABLE_NAME, row_fk, FIELD_NAME, FIELD_VALUE, most_recent, DATE_TIME

उदाहरण: 1, 4232, 'Gnarls Barkley', ' f2ff3f8822ff23 ',' 234.432.324.694 ',' अद्यतन ',' उपयोगकर्ता ', 4232,' first_name ',' gnarles ',' y ',' 2009-08-20 10:10:10 ';

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