SQL सर्वर तालिका में परिवर्तनों का पता लगाना


13

मेरे एप्लिकेशन में, SQL Server 2012 पर चल रहे DB के साथ, मुझे एक नौकरी (निर्धारित कार्य) मिली है जो समय-समय पर एक महंगी क्वेरी को निष्पादित करती है और परिणामों को एक तालिका में लिखती है जिसे बाद में आवेदन द्वारा क्वेर किया जा सकता है।

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

मुझे निम्नलिखित विचार मिले हैं:

  • स्पष्ट रूप से एक अंतिम रूप से परिवर्तित टाइमस्टैम्प, एक "प्रश्न होना चाहिए" ध्वज लिखें, या जब भी मैं किसी स्रोत तालिका में कुछ बदलता हूं तो ट्रैकिंग तालिका में ऐसा कुछ होता है।
  • ऐसा करने के लिए एक ट्रिगर का उपयोग करें।

हालाँकि, मैं वास्तव में यह जानना चाहूंगा कि क्या मेज पर बदलावों का पता लगाने का एक हल्का तरीका है मेरे बिना स्पष्ट रूप से लेखन को ट्रैक करना। क्या मैं, उदाहरण के लिए, ROWVERSIONटेबल का "वर्तमान" या ऐसा कुछ प्राप्त कर सकता हूं ?

जवाबों:


14

नहीं, कोई नहीं है किसी भी तरह का 'अंतिम अपडेटेड' ट्रैकिंग सभी लेनदेन से एक गंभीर प्रदर्शन समस्या के रूप में चलेगा, सभी लेन-देन से, पिछले रिकॉर्ड पर नज़र रखने वाले एक रिकॉर्ड को अपडेट करने का प्रयास करेगा। यह प्रभावी रूप से केवल एक ही लेन-देन किसी भी क्षण में तालिका अद्यतन कर सकते हैं मतलब होगा, और अन्य सभी लेनदेन पहले एक करने के लिए इंतजार करना पड़ प्रतिबद्ध । पूर्ण सीरियलाइजेशन। अंतिम अपडेट शायद ही छोटा हो, यह जानने के लाभ के लिए इस तरह के प्रदर्शन के दंड के साथ तैयार होने वाले प्रवेशकों / देवों की संख्या शायद कम है।

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

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

लेकिन अंत में, आपकी जगह पर, मैं वास्तव में अपनी मान्यताओं पर पुनर्विचार करूंगा और ड्राइंग बोर्ड पर वापस जाऊंगा। शायद आप किसी भिन्न सर्वर पर रिपोर्टिंग डेटाबेस सेट करने के लिए लॉग शिपिंग या प्रतिकृति का उपयोग कर सकते हैं। मैंने लाइनों के बीच जो पढ़ा है वह यह है कि आपको उचित ईटीएल पाइप-लाइन और एक एनालिटिक्स डेटा वेयरहाउस की आवश्यकता है ...


तो क्यों Microsoft sysinos_db_index_usage_stats बनाने में परेशान करेगा, अगर इसकी जानकारी प्रदान करने पर भरोसा नहीं किया जा सकता है?
क्रेग एफ्रेइन

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

8

ऐसा लगता है कि मैं खेल के लिए दो साल की देरी से यहां आया हूं, लेकिन वास्तव में आप जो कर रहे हैं उसे करने का एक बहुत हल्का तरीका है।

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

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

रोवर्सन / टाइमस्टैम्प । यह एक 8-बाइट वर्बिनरी कॉलम प्रकार (एक BigInt के लिए कास्टेबल) है जो कि बढ़ा हुआ, डेटाबेस चौड़ा होता है, जब भी एक पंक्ति जिसमें एक डाला जाता है या अपडेट किया जाता है (यह डिलीट करने में मदद नहीं करता है)। यदि आप इन स्तंभों को अनुक्रमित करते हैं, तो आप आसानी से बता सकते हैं कि पिछली बार मूल्यांकन किए जाने के बाद से अधिकतम (अधिकतम समय) इसकी कीमत के साथ पंक्ति डेटा बदल गया है। चूंकि मान नीरस रूप से बढ़ रहा है, यह आपको एक विश्वसनीय संकेत देगा कि डेटा बदल गया है यदि नया मूल्य पिछली बार आपने इसे जांचा था, तो इससे बड़ा है।


7

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

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

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

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

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


3

SqlTableDependency

SqlTableD निर्भरता SQL सर्वर डेटाबेस पर तालिका रिकॉर्ड मान वाले सूचनाओं तक पहुँचने के लिए एक उच्च-स्तरीय कार्यान्वयन घटक है।

SqlTableD निर्भरता एक सामान्य C # घटक है जिसका उपयोग सूचना प्राप्त करने के लिए किया जाता है जब एक निर्दिष्ट डेटाबेस तालिका की सामग्री बदल जाती है।

.NET SqlDepenency के साथ क्या अंतर है?

मूल रूप से, मुख्य अंतर यह है कि SqlTableD dependency रिकॉर्ड में डाले गए, बदले गए या हटाए गए, साथ ही टेबल पर निष्पादित DML ऑपरेशन (इन्सर्ट / डिलीट / अपडेट) के लिए मान भेजती है: SqlDepenency यह बताती है कि डेटा किस पर बदला गया था डेटाबेस तालिका, वे केवल कहते हैं कि कुछ बदल गया है।

GITHUB परियोजना पर एक नज़र है ।


1

यदि आप जिस अपडेट की अपेक्षा कर रहे हैं, वह किसी इंडेक्स (और केवल अगर) को प्रभावित करता है , तो आप sys.dm_db_index_usage_statsप्रश्न में टेबल पर एक इंडेक्स में अंतिम अपडेट का पता लगाने के लिए सिस्टम टेबल का उपयोग कर सकते हैं । आप last_user_updateफ़ील्ड का उपयोग करेंगे ।

उदाहरण के लिए, सबसे हाल ही में अद्यतन की गई तालिकाएँ प्राप्त करने के लिए:

select
    object_name(object_id) as OBJ_NAME, *
from
    sys.dm_db_index_usage_stats
where
    database_id = db_id(db_name())
order by
    dm_db_index_usage_stats.last_user_update desc

या, यह जांचने के लिए कि क्या किसी विशिष्ट तिथि से एक विशिष्ट तालिका बदल दी गई थी:

select
    case when count(distinct object_id) > 0 then 1 else 0 end as IS_CHANGED
from
    sys.dm_db_index_usage_stats
where
    database_id = db_id(db_name())
    and object_id = object_id('MY_TABLE_NAME')
    and last_user_update > '2016-02-18'

ऊपर रेमस की टिप्पणी पर आपकी क्या राय है? "वर्तमान पहचान में चुपके या sysinos_db_index_usage_stats की तरह कुछ 'चतुर' समाधान के साथ धोखा करने की कोशिश न करें।" (उनके जवाब के नीचे उनकी टिप्पणी भी देखें।)
फैबियन श्मिट

1
@FabianSchmied रुचिकर - मैंने यह नहीं देखा था कि जब मैंने अपना उत्तर जोड़ा था तो मुझे रेमस के एक और उत्तर के अलावा कुछ भी आधिकारिक नहीं मिला, जिससे यह संकेत मिलता है कि यह इस उपयोग-मामले के लिए अविश्वसनीय है; dm_db_index_operational_statsशो के मुद्दों के लिए एमएस पेज (मेटाडेटा कैश के रूप में साफ़ किया गया), लेकिन इसके लिए नहीं dm_db_index_usage_stats। एकमात्र मुद्दा जो मुझे मिला, वह था इंडेक्स रियड्स, सर्वर रीस्टार्ट्स और डेटाबेस डिटैचमेंट यूज़ स्टैटिस्टिक्स क्लीयर करना, और यह ऐसा नहीं लगता था कि यहाँ लागू होता है। इस पर पुष्ट जानकारी देखने के लिए इच्छुक होंगे।
ज्योफ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.