Database
 sql >> डेटाबेस >  >> RDS >> Database

पुरानी रिपोर्ट को ठीक करने के लिए AT TIME ZONE का उपयोग करना

जैसे ही मैंने SQL 2016 फीचर AT TIME ZONE देखा, जिसके बारे में मैंने यहां sqlperformance.com पर लिखा था। कुछ महीने पहले, मुझे एक रिपोर्ट याद आई जिसमें इस सुविधा की आवश्यकता थी। यह पोस्ट एक केस स्टडी बनाता है कि मैंने इसे कैसे काम करते देखा, जो मैट गॉर्डन (@sqlatspeed) द्वारा होस्ट किए गए इस महीने के टी-एसक्यूएल मंगलवार में फिट बैठता है। (यह 87वां टी-एसक्यूएल मंगलवार है, और मुझे वास्तव में और अधिक ब्लॉग पोस्ट लिखने की जरूरत है, विशेष रूप से उन चीजों के बारे में जो टी-एसक्यूएल मंगलवारों द्वारा प्रेरित नहीं हैं।)

स्थिति यह थी, और यह परिचित लग सकता है यदि आप मेरी पिछली पोस्ट को पढ़ते हैं।

लॉबस्टरपॉट सॉल्यूशंस के अस्तित्व में आने से बहुत पहले, मुझे हुई घटनाओं पर एक रिपोर्ट तैयार करने की आवश्यकता थी, और विशेष रूप से, एसएलए के भीतर प्रतिक्रियाओं की संख्या और एसएलए छूटने की संख्या दिखाएं। उदाहरण के लिए, एक सेव2 घटना जो एक कार्यदिवस पर शाम 4:30 बजे हुई, उसके लिए 1 घंटे के भीतर प्रतिक्रिया की आवश्यकता होगी, जबकि एक सेव2 घटना जो एक कार्यदिवस पर शाम 5:30 बजे हुई थी, उसे 3 घंटे के भीतर प्रतिक्रिया देने की आवश्यकता होगी। या ऐसा कुछ - मैं शामिल नंबरों को भूल जाता हूं, लेकिन मुझे याद है कि हेल्पडेस्क कर्मचारी राहत की सांस लेंगे जब शाम 5 बजे घूमेंगे, क्योंकि उन्हें चीजों पर इतनी जल्दी प्रतिक्रिया देने की आवश्यकता नहीं होगी। 15-मिनट के सेव1 अलर्ट अचानक एक घंटे तक फैल जाएंगे, और अत्यावश्यकता गायब हो जाएगी।

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

मुझे यकीन है कि यदि आपने डेटाबेस से निपटा है, तो आप उस दर्द को जान लेंगे जो डेलाइट सेविंग टाइम है। माना जाता है कि बेन फ्रैंकलिन ने इस विचार के साथ आया था - और उसके लिए उसे बिजली या कुछ और मारा जाना चाहिए। पश्चिमी ऑस्ट्रेलिया ने हाल ही में इसे कुछ वर्षों तक आजमाया और समझदारी से इसे छोड़ दिया। और आम सहमति यूटीसी में ऐसा करने के लिए दिनांक/समय डेटा स्टोर करना है।

यदि आप यूटीसी में डेटा स्टोर नहीं करते हैं, तो आप एक घटना के 2:45 बजे शुरू होने का जोखिम उठाते हैं और घड़ियां वापस जाने के बाद 2:15 बजे समाप्त होते हैं। या एक SLA घटना हो रही है जो घड़ियों के आगे बढ़ने से ठीक पहले 1:59 बजे शुरू होती है। अब, यदि आप उस समय क्षेत्र को संग्रहीत करते हैं जिसमें वे हैं, तो ये समय ठीक है, लेकिन UTC समय में अपेक्षा के अनुरूप काम करता है।

...रिपोर्टिंग को छोड़कर।

क्योंकि मुझे कैसे पता चलेगा कि कोई विशेष तिथि डेलाइट सेविंग शुरू होने से पहले या बाद में थी या नहीं? मुझे पता हो सकता है कि यूटीसी में सुबह 6:30 बजे एक घटना हुई, लेकिन क्या वह मेलबर्न में शाम 4:30 बजे या शाम 5:30 बजे है? स्पष्ट रूप से मैं विचार कर सकता हूं कि यह किस महीने में है, क्योंकि मुझे पता है कि मेलबर्न अक्टूबर में पहले रविवार से अप्रैल के पहले रविवार तक डेलाइट सेविंग टाइम देखता है, लेकिन फिर अगर ब्रिस्बेन, और ऑकलैंड, और लॉस एंजिल्स और फीनिक्स में ग्राहक हैं, और इंडियाना के भीतर विभिन्न स्थानों पर चीजें बहुत अधिक जटिल हो जाती हैं।

इसे दूर करने के लिए, बहुत कम समय क्षेत्र थे जिनमें उस कंपनी के लिए SLAs को परिभाषित किया जा सकता था। इससे अधिक की पूर्ति करना अभी बहुत कठिन माना जाता था। फिर एक रिपोर्ट को यह कहने के लिए अनुकूलित किया जा सकता है कि "विचार करें कि किसी विशेष तिथि पर समय क्षेत्र X से Y में बदल गया है"। यह गन्दा लगा, लेकिन इसने काम किया। Windows रजिस्ट्री को देखने के लिए किसी चीज़ की आवश्यकता नहीं थी, और यह मूल रूप से बस काम कर गया।

लेकिन इन दिनों, मैंने इसे अलग तरह से किया होता।

अब, मैं AT TIME ZONE का उपयोग करता।

आप देखिए, अब मैं ग्राहक के समय क्षेत्र की जानकारी को ग्राहक की संपत्ति के रूप में संग्रहीत कर सकता हूं। फिर मैं प्रत्येक घटना समय को यूटीसी में संग्रहीत कर सकता था, जिससे मुझे ग्राहक के स्थानीय समय का उपयोग करके रिपोर्ट करने में सक्षम होने के साथ-साथ प्रतिक्रिया देने, हल करने आदि के लिए मिनटों की संख्या के आसपास आवश्यक गणना करने की अनुमति मिलती है। यह मानते हुए कि मेरा इंसिडेंटटाइम वास्तव में डेटाटाइम का उपयोग करके संग्रहीत किया गया था, डेटाटाइमऑफ़सेट के बजाय, यह केवल कोड का उपयोग करने की बात होगी:

i.IncidentTime AT TIME ZONE 'UTC' AT TIME ZONE c.tz

…जो पहले टाइमज़ोनलेस i.IncidentTime को UTC में डालता है, इसे ग्राहक के टाइम ज़ोन में बदलने से पहले। और यह समय क्षेत्र 'एयूएस पूर्वी मानक समय', या 'मॉरीशस मानक समय', या जो भी हो सकता है। और SQL इंजन को यह पता लगाने के लिए छोड़ दिया जाता है कि उसके लिए किस ऑफ़सेट का उपयोग करना है।

इस बिंदु पर, मैं बहुत आसानी से एक रिपोर्ट बना सकता हूं जो प्रत्येक घटना को एक समयावधि में सूचीबद्ध करती है, और इसे ग्राहक के स्थानीय समय क्षेत्र में दिखाती है। मैं मान को समय डेटा प्रकार में परिवर्तित कर सकता हूं, और फिर रिपोर्ट कर सकता हूं कि व्यावसायिक घंटों के भीतर कितनी घटनाएं हुईं या नहीं।

और यह सब बहुत उपयोगी है, लेकिन इसे अच्छी तरह से संभालने के लिए अनुक्रमण के बारे में क्या? आखिर AT TIME ZONE एक फंक्शन है। लेकिन समय क्षेत्र बदलने से उस क्रम में बदलाव नहीं आता जिसमें वास्तव में घटनाएं हुईं, इसलिए यह ठीक होना चाहिए।

इसका परीक्षण करने के लिए, मैंने dbo.Incidents नामक एक तालिका बनाई, और IncidentTime कॉलम को अनुक्रमित किया। फिर मैंने इस क्वेरी को चलाया, और पुष्टि की कि एक इंडेक्स सीक का उपयोग किया गया था।

select i.IncidentTime, itz.LocalTime
from dbo.Incidents i
cross apply (select i.IncidentTime AT TIME ZONE 'UTC' 
  AT TIME ZONE 'Cen. Australia Standard Time') itz (LocalTime)
where i.IncidentTime >= '20170201'
and i.IncidentTime < '20170301';

लेकिन मैं itz.LocalTime…

. पर फ़िल्टर करना चाहता हूँ
select i.IncidentTime, itz.LocalTime
from dbo.Incidents i
cross apply (select i.IncidentTime AT TIME ZONE 'UTC' 
  AT TIME ZONE 'Cen. Australia Standard Time') itz (LocalTime)
where itz.LocalTime >= '20170201'
and itz.LocalTime < '20170301';

कोई भाग्य नहीं। यह सूचकांक पसंद नहीं आया।

चेतावनियां इसलिए हैं क्योंकि इसे उस डेटा से कहीं अधिक देखना है जिसमें मुझे रूचि है।

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

select i.IncidentTime, itz.LocalTime
from dbo.IncidentsOffset i
cross apply (select i.IncidentTime AT TIME ZONE 'Cen. Australia Standard Time') itz (LocalTime)
where itz.LocalTime >= cast('20170201' as datetimeoffset) 
  AT TIME ZONE 'Cen. Australia Standard Time'
and itz.LocalTime < cast('20170301' as datetimeoffset) 
  AT TIME ZONE 'Cen. Australia Standard Time';

फिर भी किस्मत नहीं!

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

दूसरा विकल्प यह था कि मैं जिसे हेल्पर विधेय कहता हूं उसका उपयोग करना। जब आप LIKE का उपयोग करते हैं तो ये ऐसी चीजें होती हैं जो आपको दिखाई देती हैं। वे विधेय हैं जिनका उपयोग सीक प्रेडिकेट्स के रूप में किया जा सकता है, लेकिन ठीक वैसा नहीं जैसा आप पूछ रहे हैं।

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

इसलिए मैं दो अतिरिक्त विधेय शामिल करूंगा।

select i.IncidentTime, itz.LocalTime
from dbo.IncidentsOffset i
cross apply (select i.IncidentTime 
    AT TIME ZONE 'Cen. Australia Standard Time') itz (LocalTime)
where itz.LocalTime >= cast('20170201' as datetimeoffset) 
  AT TIME ZONE 'Cen. Australia Standard Time'
and itz.LocalTime < cast('20170301' as datetimeoffset) 
  AT TIME ZONE 'Cen. Australia Standard Time
and i.IncidentTime >= dateadd(day,-1,'20170201')
and i.IncidentTime < dateadd(day, 1,'20170301');

अब, मेरी अनुक्रमणिका का उपयोग किया जा सकता है। इसे 28 पर फ़िल्टर करने से पहले 30 पंक्तियों के माध्यम से देखना होगा - लेकिन यह पूरी चीज़ को स्कैन करने की तुलना में बहुत बेहतर है।

और आप जानते हैं - इस तरह का व्यवहार मैं नियमित प्रश्नों से हर समय देखता हूं, जैसे कि जब मैं CAST(myDateTimeColumns AS DATE) =@SomeDate करता हूं, या LIKE का उपयोग करता हूं।

मैं इसके साथ ठीक हूँ। AT TIME ZONE मुझे अपने समय क्षेत्र रूपांतरणों को संभालने के लिए बहुत अच्छा है, और मेरे प्रश्नों के साथ क्या हो रहा है, इस पर विचार करके, मुझे प्रदर्शन का त्याग करने की भी आवश्यकता नहीं है।

@rob_farley


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL में एक संख्यात्मक कॉलम का अधिकतम मान कैसे खोजें

  2. NULL के 50 शेड्स – SQL में NULL के विभिन्न अर्थ

  3. WP-CLI का उपयोग करके वर्डप्रेस इंस्टाल करना

  4. व्यस्त डेटा लोगों के लिए 7 नि:शुल्क डेटाबेस आरेखण उपकरण

  5. कस्टम निर्मित सांख्यिकी